Print this page
    
OS-2366 ddi_periodic_add(9F) is entirely rubbish
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/os/damap.c
          +++ new/usr/src/uts/common/os/damap.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   */
  25   25  
  26   26  #include <sys/note.h>
  
    | ↓ open down ↓ | 26 lines elided | ↑ open up ↑ | 
  27   27  #include <sys/types.h>
  28   28  #include <sys/param.h>
  29   29  #include <sys/systm.h>
  30   30  #include <sys/buf.h>
  31   31  #include <sys/kmem.h>
  32   32  #include <sys/cmn_err.h>
  33   33  #include <sys/debug.h>
  34   34  #include <sys/sunndi.h>
  35   35  #include <sys/kstat.h>
  36   36  #include <sys/conf.h>
  37      -#include <sys/ddi_timer.h>
       37 +#include <sys/ddi_periodic.h>
  38   38  #include <sys/devctl.h>
  39   39  #include <sys/callb.h>
  40   40  #include <sys/sysevent.h>
  41   41  #include <sys/taskq.h>
  42   42  #include <sys/ddi.h>
  43   43  #include <sys/bitset.h>
  44   44  #include <sys/damap.h>
  45   45  #include <sys/damap_impl.h>
  46   46  
  47   47  #ifdef DEBUG
  48   48  static int damap_debug = 0;
  49   49  #endif /* DEBUG */
  50   50  
  51   51  extern taskq_t *system_taskq;
  52   52  
  53   53  static void dam_addrset_activate(dam_t *, bitset_t *);
  54   54  static void dam_addrset_deactivate(dam_t *, bitset_t *);
  55   55  static void dam_stabilize_map(void *);
  56   56  static void dam_addr_stable_cb(void *);
  57   57  static void dam_addrset_stable_cb(void *);
  58   58  static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t);
  59   59  static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
  60   60  static void dam_addr_release(dam_t *, id_t);
  61   61  static void dam_addr_report_release(dam_t *, id_t);
  62   62  static void dam_addr_deactivate(dam_t *, id_t);
  63   63  static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
  64   64  static id_t dam_get_addrid(dam_t *, char *);
  65   65  static int dam_kstat_create(dam_t *);
  66   66  static int dam_map_alloc(dam_t *);
  67   67  
  68   68  #define DAM_INCR_STAT(mapp, stat)                               \
  69   69          if ((mapp)->dam_kstatsp) {                              \
  70   70                  struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;  \
  71   71                  stp->stat.value.ui32++;                         \
  72   72          }
  73   73  
  74   74  #define DAM_SET_STAT(mapp, stat, val)                           \
  75   75          if ((mapp)->dam_kstatsp) {                              \
  76   76                  struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;  \
  77   77                  stp->stat.value.ui32 = (val);                   \
  78   78          }
  79   79  
  80   80  
  81   81  /*
  82   82   * increase damap size by 64 entries at a time
  83   83   */
  84   84  #define DAM_SIZE_BUMP   64
  85   85  
  86   86  int     damap_taskq_dispatch_retry_usec = 1000;
  87   87  
  88   88  /*
  89   89   * config/unconfig taskq data
  90   90   */
  91   91  typedef struct {
  92   92          dam_t *tqd_mapp;
  93   93          id_t tqd_id;
  94   94  } cfg_tqd_t;
  95   95  
  96   96  extern pri_t maxclsyspri;
  97   97  
  98   98  /*
  99   99   * Create new device address map
 100  100   *
 101  101   * name:                map name (kstat unique)
 102  102   * size:                max # of map entries
 103  103   * mode:                style of address reports: per-address or fullset
 104  104   * stable_usec:         # of quiescent microseconds before report/map is stable
 105  105   *
 106  106   * activate_arg:        address provider activation-callout private
 107  107   * activate_cb:         address provider activation callback handler
 108  108   * deactivate_cb:       address provider deactivation callback handler
 109  109   *
 110  110   * config_arg:          configuration-callout private
 111  111   * config_cb:           class configuration callout
 112  112   * unconfig_cb:         class unconfiguration callout
 113  113   *
 114  114   * damapp:              pointer to map handle (return)
 115  115   *
 116  116   * Returns:     DAM_SUCCESS
 117  117   *              DAM_EINVAL      Invalid argument(s)
 118  118   *              DAM_FAILURE     General failure
 119  119   */
 120  120  int
 121  121  damap_create(char *name, damap_rptmode_t mode, int map_opts,
 122  122      int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
 123  123      damap_deactivate_cb_t deactivate_cb,
 124  124      void *config_arg, damap_configure_cb_t configure_cb,
 125  125      damap_unconfig_cb_t unconfig_cb,
 126  126      damap_t **damapp)
 127  127  {
 128  128          dam_t *mapp;
 129  129  
 130  130          if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
 131  131                  return (DAM_EINVAL);
 132  132  
 133  133          mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
 134  134          mapp->dam_options = map_opts;
 135  135          mapp->dam_stable_ticks = drv_usectohz(stable_usec);
 136  136          mapp->dam_size = 0;
 137  137          mapp->dam_rptmode = mode;
 138  138          mapp->dam_activate_arg = activate_arg;
 139  139          mapp->dam_activate_cb = (activate_cb_t)activate_cb;
 140  140          mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
 141  141          mapp->dam_config_arg = config_arg;
 142  142          mapp->dam_configure_cb = (configure_cb_t)configure_cb;
 143  143          mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
 144  144          mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
 145  145          mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
 146  146          cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL);
 147  147          bitset_init(&mapp->dam_active_set);
 148  148          bitset_init(&mapp->dam_stable_set);
 149  149          bitset_init(&mapp->dam_report_set);
 150  150          *damapp = (damap_t *)mapp;
 151  151  
 152  152          DTRACE_PROBE5(damap__create,
 153  153              char *, mapp->dam_name, damap_t *, mapp,
 154  154              damap_rptmode_t, mode, int, map_opts, int, stable_usec);
 155  155  
 156  156          return (DAM_SUCCESS);
 157  157  }
 158  158  
 159  159  /*
 160  160   * Allocate backing resources
 161  161   *
 162  162   * DAMs are lightly backed on create - major allocations occur
 163  163   * at the time a report is made to the map, and are extended on
 164  164   * a demand basis.
 165  165   */
 166  166  static int
 167  167  dam_map_alloc(dam_t *mapp)
 168  168  {
 169  169          void *softstate_p;
 170  170  
 171  171          ASSERT(mutex_owned(&mapp->dam_lock));
 172  172          if (mapp->dam_flags & DAM_DESTROYPEND)
 173  173                  return (DAM_FAILURE);
 174  174  
 175  175          /*
 176  176           * dam_high > 0 signals map allocation complete
 177  177           */
 178  178          if (mapp->dam_high)
 179  179                  return (DAM_SUCCESS);
 180  180  
 181  181          mapp->dam_size = DAM_SIZE_BUMP;
 182  182          if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
 183  183              mapp->dam_size) != DDI_SUCCESS)
 184  184                  return (DAM_FAILURE);
 185  185  
 186  186          if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
 187  187              DDI_SUCCESS) {
 188  188                  ddi_soft_state_fini(softstate_p);
 189  189                  return (DAM_FAILURE);
 190  190          }
 191  191          if (dam_kstat_create(mapp) != DDI_SUCCESS) {
 192  192                  ddi_soft_state_fini(softstate_p);
 193  193                  ddi_strid_fini(&mapp->dam_addr_hash);
 194  194                  return (DAM_FAILURE);
 195  195          }
 196  196          mapp->dam_da = softstate_p;
 197  197          mapp->dam_high = 1;
 198  198          bitset_resize(&mapp->dam_active_set, mapp->dam_size);
 199  199          bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
 200  200          bitset_resize(&mapp->dam_report_set, mapp->dam_size);
 201  201          return (DAM_SUCCESS);
 202  202  }
 203  203  
 204  204  /*
 205  205   * Destroy address map
 206  206   *
 207  207   * damapp:      address map
 208  208   *
 209  209   * Returns:     DAM_SUCCESS
 210  210   *              DAM_EINVAL      Invalid argument(s)
 211  211   *              DAM_FAILURE     General failure
 212  212   */
 213  213  void
 214  214  damap_destroy(damap_t *damapp)
 215  215  {
 216  216          int i;
 217  217          dam_t *mapp = (dam_t *)damapp;
 218  218  
 219  219          ASSERT(mapp);
 220  220  
 221  221          DTRACE_PROBE2(damap__destroy,
 222  222              char *, mapp->dam_name, damap_t *, mapp);
 223  223  
 224  224          mutex_enter(&mapp->dam_lock);
 225  225  
 226  226          /*
 227  227           * prevent new reports from being added to the map
 228  228           */
 229  229          mapp->dam_flags |= DAM_DESTROYPEND;
 230  230  
 231  231          if (mapp->dam_high) {
 232  232                  mutex_exit(&mapp->dam_lock);
 233  233                  /*
 234  234                   * wait for outstanding reports to stabilize and cancel
 235  235                   * the timer for this map
 236  236                   */
 237  237                  (void) damap_sync(damapp, 0);
 238  238                  mutex_enter(&mapp->dam_lock);
 239  239                  dam_sched_timeout(NULL, mapp, 0);
 240  240  
 241  241                  /*
 242  242                   * map is at full stop
 243  243                   * release the contents of the map, invoking the
 244  244                   * detactivation protocol as addresses are released
 245  245                   */
 246  246                  mutex_exit(&mapp->dam_lock);
 247  247                  for (i = 1; i < mapp->dam_high; i++) {
 248  248                          if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
 249  249                                  continue;
 250  250  
 251  251                          ASSERT(DAM_IN_REPORT(mapp, i) == 0);
 252  252  
 253  253                          if (DAM_IS_STABLE(mapp, i)) {
 254  254                                  dam_addr_deactivate(mapp, i);
 255  255                          } else {
 256  256                                  ddi_strid_free(mapp->dam_addr_hash, i);
 257  257                                  ddi_soft_state_free(mapp->dam_da, i);
 258  258                          }
 259  259                  }
 260  260                  ddi_strid_fini(&mapp->dam_addr_hash);
 261  261                  ddi_soft_state_fini(&mapp->dam_da);
 262  262                  kstat_delete(mapp->dam_kstatsp);
 263  263          } else
 264  264                  mutex_exit(&mapp->dam_lock);
 265  265  
 266  266          bitset_fini(&mapp->dam_active_set);
 267  267          bitset_fini(&mapp->dam_stable_set);
 268  268          bitset_fini(&mapp->dam_report_set);
 269  269          mutex_destroy(&mapp->dam_lock);
 270  270          cv_destroy(&mapp->dam_sync_cv);
 271  271          if (mapp->dam_name)
 272  272                  kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
 273  273          kmem_free(mapp, sizeof (*mapp));
 274  274  }
 275  275  
 276  276  /*
 277  277   * Wait for map stability.  If sync was successfull then return 1.
 278  278   * If called with a non-zero sync_usec, then a return value of 0 means a
 279  279   * timeout occurred prior to sync completion. NOTE: if sync_usec is
 280  280   * non-zero, it should be much longer than dam_stable_ticks.
 281  281   *
 282  282   * damapp:      address map
 283  283   * sync_usec:   micorseconds until we give up on sync completion.
 284  284   */
 285  285  #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
 286  286  int
 287  287  damap_sync(damap_t *damapp, int sync_usec)
 288  288  {
 289  289          dam_t   *mapp = (dam_t *)damapp;
 290  290          int     rv;
 291  291  
 292  292          ASSERT(mapp);
 293  293          DTRACE_PROBE3(damap__map__sync__start,
 294  294              char *, mapp->dam_name, dam_t *, mapp,
 295  295              int, sync_usec);
 296  296  
 297  297          /*
 298  298           * Block when waiting for
 299  299           *      a) stabilization pending or a fullset update pending
 300  300           *      b) the report set to finalize (bitset is null)
 301  301           *      c) any scheduled timeouts to fire
 302  302           */
 303  303          rv = 1;                                 /* return synced */
 304  304          mutex_enter(&mapp->dam_lock);
 305  305  again:  while ((mapp->dam_flags & WAITFOR_FLAGS) ||
 306  306              (!bitset_is_null(&mapp->dam_report_set)) ||
 307  307              (mapp->dam_tid != 0)) {
 308  308                  DTRACE_PROBE2(damap__map__sync__waiting,
 309  309                      char *, mapp->dam_name, dam_t *, mapp);
 310  310  
 311  311                  /* Wait for condition relayed via timeout */
 312  312                  if (sync_usec) {
 313  313                          if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
 314  314                              drv_usectohz(sync_usec), TR_MICROSEC) == -1) {
 315  315                                  mapp->dam_sync_to_cnt++;
 316  316                                  rv = 0;         /* return timeout */
 317  317                                  break;
 318  318                          }
 319  319                  } else
 320  320                          cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
 321  321          }
 322  322  
 323  323          if (rv) {
 324  324                  /*
 325  325                   * Delay one stabilization time after the apparent sync above
 326  326                   * and verify accuracy - resync if not accurate.
 327  327                   */
 328  328                  (void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
 329  329                      mapp->dam_stable_ticks, TR_MICROSEC);
 330  330                  if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) ||
 331  331                      (!bitset_is_null(&mapp->dam_report_set)) ||
 332  332                      (mapp->dam_tid != 0)))
 333  333                          goto again;
 334  334          }
 335  335          mutex_exit(&mapp->dam_lock);
 336  336  
 337  337          DTRACE_PROBE3(damap__map__sync__end,
 338  338              char *, mapp->dam_name, dam_t *, mapp,
 339  339              int, rv);
 340  340          return (rv);
 341  341  }
 342  342  
 343  343  /*
 344  344   * Return 1 if active set is empty
 345  345   */
 346  346  int
 347  347  damap_is_empty(damap_t *damapp)
 348  348  {
 349  349          dam_t   *mapp = (dam_t *)damapp;
 350  350          int     rv;
 351  351  
 352  352          mutex_enter(&mapp->dam_lock);
 353  353          rv = bitset_is_null(&mapp->dam_active_set);
 354  354          mutex_exit(&mapp->dam_lock);
 355  355          return (rv);
 356  356  }
 357  357  
 358  358  /*
 359  359   * Get the name of a device address map
 360  360   *
 361  361   * damapp:      address map
 362  362   *
 363  363   * Returns:     name
 364  364   */
 365  365  char *
 366  366  damap_name(damap_t *damapp)
 367  367  {
 368  368          dam_t *mapp = (dam_t *)damapp;
 369  369  
 370  370          return (mapp ? mapp->dam_name : "UNKNOWN_damap");
 371  371  }
 372  372  
 373  373  /*
 374  374   * Get the current size of the device address map
 375  375   *
 376  376   * damapp:      address map
 377  377   *
 378  378   * Returns:     size
 379  379   */
 380  380  int
 381  381  damap_size(damap_t *damapp)
 382  382  {
 383  383          dam_t *mapp = (dam_t *)damapp;
 384  384  
 385  385          return (mapp->dam_size);
 386  386  }
 387  387  
 388  388  /*
 389  389   * Report an address to per-address report
 390  390   *
 391  391   * damapp:      address map handle
 392  392   * address:     address in ascii string representation
 393  393   * addridp:     address ID
 394  394   * nvl:         optional nvlist of configuration-private data
 395  395   * addr_priv:   optional provider-private (passed to activate/deactivate cb)
 396  396   *
 397  397   * Returns:     DAM_SUCCESS
 398  398   *              DAM_EINVAL      Invalid argument(s)
 399  399   *              DAM_MAPFULL     address map exhausted
 400  400   */
 401  401  int
 402  402  damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
 403  403      nvlist_t *nvl, void *addr_priv)
 404  404  {
 405  405          dam_t *mapp = (dam_t *)damapp;
 406  406          id_t addrid;
 407  407          dam_da_t *passp;
 408  408  
 409  409          if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
 410  410                  return (DAM_EINVAL);
 411  411  
 412  412          DTRACE_PROBE3(damap__addr__add,
 413  413              char *, mapp->dam_name, dam_t *, mapp,
 414  414              char *, address);
 415  415  
 416  416          mutex_enter(&mapp->dam_lock);
 417  417          if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
 418  418              ((addrid = dam_get_addrid(mapp, address)) == 0)) {
 419  419                  mutex_exit(&mapp->dam_lock);
 420  420                  return (DAM_MAPFULL);
 421  421          }
 422  422  
 423  423          passp = ddi_get_soft_state(mapp->dam_da, addrid);
 424  424          ASSERT(passp != NULL);
 425  425  
 426  426          /*
 427  427           * If re-reporting the same address (add or remove) clear
 428  428           * the existing report
 429  429           */
 430  430          if (DAM_IN_REPORT(mapp, addrid)) {
 431  431                  DTRACE_PROBE3(damap__addr__add__jitter,
 432  432                      char *, mapp->dam_name, dam_t *, mapp,
 433  433                      char *, address);
 434  434                  DAM_INCR_STAT(mapp, dam_jitter);
 435  435                  dam_addr_report_release(mapp, addrid);
 436  436                  passp->da_jitter++;
 437  437          }
 438  438          passp->da_ppriv_rpt = addr_priv;
 439  439          if (nvl)
 440  440                  (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
 441  441  
 442  442          dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
 443  443          if (addridp != NULL)
 444  444                  *addridp = (damap_id_t)addrid;
 445  445          mutex_exit(&mapp->dam_lock);
 446  446          return (DAM_SUCCESS);
 447  447  }
 448  448  
 449  449  /*
 450  450   * Report removal of address from per-address report
 451  451   *
 452  452   * damapp:      address map
 453  453   * address:     address in ascii string representation
 454  454   *
 455  455   * Returns:     DAM_SUCCESS
 456  456   *              DAM_EINVAL      Invalid argument(s)
 457  457   *              DAM_FAILURE     General failure
 458  458   */
 459  459  int
 460  460  damap_addr_del(damap_t *damapp, char *address)
 461  461  {
 462  462          dam_t *mapp = (dam_t *)damapp;
 463  463          id_t addrid;
 464  464          dam_da_t *passp;
 465  465  
 466  466          if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
 467  467                  return (DAM_EINVAL);
 468  468  
 469  469          DTRACE_PROBE3(damap__addr__del,
 470  470              char *, mapp->dam_name, dam_t *, mapp,
 471  471              char *, address);
 472  472          mutex_enter(&mapp->dam_lock);
 473  473          if (dam_map_alloc(mapp) != DAM_SUCCESS) {
 474  474                  mutex_exit(&mapp->dam_lock);
 475  475                  return (DAM_MAPFULL);
 476  476          }
 477  477  
 478  478          /*
 479  479           * if reporting the removal of an address which is not in the map
 480  480           * return success
 481  481           */
 482  482          if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
 483  483                  mutex_exit(&mapp->dam_lock);
 484  484                  return (DAM_SUCCESS);
 485  485          }
 486  486          passp = ddi_get_soft_state(mapp->dam_da, addrid);
 487  487          ASSERT(passp);
 488  488          if (DAM_IN_REPORT(mapp, addrid)) {
 489  489                  DTRACE_PROBE3(damap__addr__del__jitter,
 490  490                      char *, mapp->dam_name, dam_t *, mapp,
 491  491                      char *, address);
 492  492                  DAM_INCR_STAT(mapp, dam_jitter);
 493  493                  dam_addr_report_release(mapp, addrid);
 494  494                  passp->da_jitter++;
 495  495          }
 496  496          dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
 497  497          mutex_exit(&mapp->dam_lock);
 498  498          return (DAM_SUCCESS);
 499  499  }
 500  500  
 501  501  static int
 502  502  damap_addrset_flush_locked(damap_t *damapp)
 503  503  {
 504  504          dam_t   *mapp = (dam_t *)damapp;
 505  505          int     idx;
 506  506  
 507  507          ASSERT(mapp);
 508  508          ASSERT(mutex_owned(&mapp->dam_lock));
 509  509          if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
 510  510                  return (DAM_EINVAL);
 511  511          }
 512  512  
 513  513          DTRACE_PROBE2(damap__addrset__flush__locked__enter,
 514  514              char *, mapp->dam_name, dam_t *, mapp);
 515  515          if (mapp->dam_flags & DAM_SETADD) {
 516  516                  DTRACE_PROBE2(damap__addrset__flush__locked__reset,
 517  517                      char *, mapp->dam_name, dam_t *, mapp);
 518  518  
 519  519                  /*
 520  520                   * cancel stabilization timeout
 521  521                   */
 522  522                  dam_sched_timeout(NULL, mapp, 0);
 523  523                  DAM_INCR_STAT(mapp, dam_jitter);
 524  524  
 525  525                  /*
 526  526                   * clear pending reports
 527  527                   */
 528  528                  for (idx = 1; idx < mapp->dam_high; idx++) {
 529  529                          if (DAM_IN_REPORT(mapp, idx)) {
 530  530                                  dam_addr_report_release(mapp, idx);
 531  531                          }
 532  532                  }
 533  533  
 534  534                  bitset_zero(&mapp->dam_report_set);
 535  535                  mapp->dam_flags &= ~DAM_SETADD;
 536  536                  cv_signal(&mapp->dam_sync_cv);
 537  537          }
 538  538  
 539  539          return (DAM_SUCCESS);
 540  540  }
 541  541  
 542  542  /*
 543  543   * Initiate full-set report
 544  544   *
 545  545   * damapp:      address map
 546  546   *
 547  547   * Returns:     DAM_SUCCESS
 548  548   *              DAM_EINVAL      Invalid argument(s)
 549  549   */
 550  550  int
 551  551  damap_addrset_begin(damap_t *damapp)
 552  552  {
 553  553          dam_t   *mapp = (dam_t *)damapp;
 554  554          int     rv;
 555  555  
 556  556          if (mapp == NULL) {
 557  557                  return (DAM_EINVAL);
 558  558          }
 559  559  
 560  560          DTRACE_PROBE2(damap__addrset__begin,
 561  561              char *, mapp->dam_name, dam_t *, mapp);
 562  562  
 563  563          mutex_enter(&mapp->dam_lock);
 564  564          if (dam_map_alloc(mapp) != DAM_SUCCESS) {
 565  565                  mutex_exit(&mapp->dam_lock);
 566  566  
 567  567                  return (DAM_MAPFULL);
 568  568          }
 569  569  
 570  570          rv = damap_addrset_flush_locked(damapp);
 571  571          if (rv == DAM_SUCCESS) {
 572  572                  mapp->dam_flags |= DAM_SETADD;
 573  573          }
 574  574          mutex_exit(&mapp->dam_lock);
 575  575  
 576  576          return (rv);
 577  577  }
 578  578  
 579  579  /*
 580  580   * Cancel full-set report
 581  581   *
 582  582   * damapp:      address map
 583  583   *
 584  584   * Returns:     DAM_SUCCESS
 585  585   *              DAM_EINVAL      Invalid argument(s)
 586  586   */
 587  587  int
 588  588  damap_addrset_flush(damap_t *damapp)
 589  589  {
 590  590          int     rv;
 591  591          dam_t   *mapp = (dam_t *)damapp;
 592  592  
 593  593          if (mapp == NULL) {
 594  594                  return (DAM_EINVAL);
 595  595          }
 596  596  
 597  597          DTRACE_PROBE2(damap__addrset__flush,
 598  598              char *, mapp->dam_name, dam_t *, mapp);
 599  599  
 600  600          mutex_enter(&mapp->dam_lock);
 601  601          rv = damap_addrset_flush_locked(damapp);
 602  602          mutex_exit(&mapp->dam_lock);
 603  603  
 604  604          return (rv);
 605  605  }
 606  606  
 607  607  /*
 608  608   * Report address to full-set report
 609  609   *
 610  610   * damapp:      address map handle
 611  611   * address:     address in ascii string representation
 612  612   * rindx:       index if address stabilizes
 613  613   * nvl:         optional nvlist of configuration-private data
 614  614   * addr_priv:   optional provider-private data (passed to activate/release cb)
 615  615   *
 616  616   * Returns:     DAM_SUCCESS
 617  617   *              DAM_EINVAL      Invalid argument(s)
 618  618   *              DAM_MAPFULL     address map exhausted
 619  619   *              DAM_FAILURE     General failure
 620  620   */
 621  621  int
 622  622  damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
 623  623      nvlist_t *nvl, void *addr_priv)
 624  624  {
 625  625          dam_t *mapp = (dam_t *)damapp;
 626  626          id_t addrid;
 627  627          dam_da_t *passp;
 628  628  
 629  629          if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
 630  630                  return (DAM_EINVAL);
 631  631  
 632  632          DTRACE_PROBE3(damap__addrset__add,
 633  633              char *, mapp->dam_name, dam_t *, mapp, char *, address);
 634  634  
 635  635          mutex_enter(&mapp->dam_lock);
 636  636          if (!(mapp->dam_flags & DAM_SETADD)) {
 637  637                  mutex_exit(&mapp->dam_lock);
 638  638                  return (DAM_FAILURE);
 639  639          }
 640  640  
 641  641          if ((addrid = dam_get_addrid(mapp, address)) == 0) {
 642  642                  mutex_exit(&mapp->dam_lock);
 643  643                  return (DAM_MAPFULL);
 644  644          }
 645  645  
 646  646          passp = ddi_get_soft_state(mapp->dam_da, addrid);
 647  647          ASSERT(passp);
 648  648          if (DAM_IN_REPORT(mapp, addrid)) {
 649  649                  DTRACE_PROBE3(damap__addrset__add__jitter,
 650  650                      char *, mapp->dam_name, dam_t *, mapp,
 651  651                      char *, address);
 652  652                  dam_addr_report_release(mapp, addrid);
 653  653                  passp->da_jitter++;
 654  654          }
 655  655          passp->da_ppriv_rpt = addr_priv;
 656  656          if (nvl)
 657  657                  (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
 658  658          bitset_add(&mapp->dam_report_set, addrid);
 659  659          if (ridx)
 660  660                  *ridx = (damap_id_t)addrid;
 661  661          mutex_exit(&mapp->dam_lock);
 662  662          return (DAM_SUCCESS);
 663  663  }
 664  664  
 665  665  /*
 666  666   * Commit full-set report for stabilization
 667  667   *
 668  668   * damapp:      address map handle
 669  669   * flags:       (currently 0)
 670  670   *
 671  671   * Returns:     DAM_SUCCESS
 672  672   *              DAM_EINVAL      Invalid argument(s)
 673  673   *              DAM_FAILURE     General failure
 674  674   */
 675  675  int
 676  676  damap_addrset_end(damap_t *damapp, int flags)
 677  677  {
 678  678          dam_t *mapp = (dam_t *)damapp;
 679  679          int i;
 680  680  
 681  681          if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
 682  682                  return (DAM_EINVAL);
 683  683  
 684  684          DTRACE_PROBE2(damap__addrset__end,
 685  685              char *, mapp->dam_name, dam_t *, mapp);
 686  686  
 687  687          mutex_enter(&mapp->dam_lock);
 688  688          if (!(mapp->dam_flags & DAM_SETADD)) {
 689  689                  mutex_exit(&mapp->dam_lock);
 690  690                  return (DAM_FAILURE);
 691  691          }
 692  692  
 693  693          if (flags & DAMAP_END_RESET) {
 694  694                  DTRACE_PROBE2(damap__addrset__end__reset,
 695  695                      char *, mapp->dam_name, dam_t *, mapp);
 696  696                  dam_sched_timeout(NULL, mapp, 0);
 697  697                  for (i = 1; i < mapp->dam_high; i++)
 698  698                          if (DAM_IN_REPORT(mapp, i))
 699  699                                  dam_addr_report_release(mapp, i);
 700  700          } else {
 701  701                  mapp->dam_last_update = gethrtime();
 702  702                  dam_sched_timeout(dam_addrset_stable_cb, mapp,
 703  703                      mapp->dam_stable_ticks);
 704  704          }
 705  705          mutex_exit(&mapp->dam_lock);
 706  706          return (DAM_SUCCESS);
 707  707  }
 708  708  
 709  709  /*
 710  710   * Return nvlist registered with reported address
 711  711   *
 712  712   * damapp:      address map handle
 713  713   * addrid:      address ID
 714  714   *
 715  715   * Returns:     nvlist_t *      provider supplied via damap_addr{set}_add())
 716  716   *              NULL
 717  717   */
 718  718  nvlist_t *
 719  719  damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
 720  720  {
 721  721          dam_t *mapp = (dam_t *)damapp;
 722  722          dam_da_t *pass;
 723  723  
 724  724          if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
 725  725                  if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
 726  726                          return (pass->da_nvl);
 727  727          }
 728  728          return (NULL);
 729  729  }
 730  730  
 731  731  /*
 732  732   * Return address string
 733  733   *
 734  734   * damapp:      address map handle
 735  735   * addrid:      address ID
 736  736   *
 737  737   * Returns:     char *          Address string
 738  738   *              NULL
 739  739   */
 740  740  char *
 741  741  damap_id2addr(damap_t *damapp, damap_id_t addrid)
 742  742  {
 743  743          dam_t *mapp = (dam_t *)damapp;
 744  744  
 745  745          if (mapp->dam_high)
 746  746                  return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
 747  747          else
 748  748                  return (NULL);
 749  749  }
 750  750  
 751  751  /*
 752  752   * Release address reference in map
 753  753   *
 754  754   * damapp:      address map handle
 755  755   * addrid:      address ID
 756  756   */
 757  757  void
 758  758  damap_id_rele(damap_t *damapp, damap_id_t addrid)
 759  759  {
 760  760          dam_t *mapp = (dam_t *)damapp;
 761  761          dam_da_t *passp;
 762  762          char *addr;
 763  763  
 764  764          passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
 765  765          ASSERT(passp);
 766  766  
 767  767          addr = damap_id2addr(damapp, addrid);
 768  768          DTRACE_PROBE4(damap__id__rele,
 769  769              char *, mapp->dam_name, dam_t *, mapp,
 770  770              char *, addr, int, passp->da_ref);
 771  771  
 772  772          mutex_enter(&mapp->dam_lock);
 773  773  
 774  774          /*
 775  775           * teardown address if last outstanding reference
 776  776           */
 777  777          if (--passp->da_ref == 0)
 778  778                  dam_addr_release(mapp, (id_t)addrid);
 779  779  
 780  780          mutex_exit(&mapp->dam_lock);
 781  781  }
 782  782  
 783  783  /*
 784  784   * Return current reference count on address reference in map
 785  785   *
 786  786   * damapp:      address map handle
 787  787   * addrid:      address ID
 788  788   *
 789  789   * Returns:     DAM_SUCCESS
 790  790   *              DAM_FAILURE
 791  791   */
 792  792  int
 793  793  damap_id_ref(damap_t *damapp, damap_id_t addrid)
 794  794  {
 795  795          dam_t *mapp = (dam_t *)damapp;
 796  796          dam_da_t *passp;
 797  797          int ref = -1;
 798  798  
 799  799          passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
 800  800          if (passp)
 801  801                  ref = passp->da_ref;
 802  802  
 803  803          return (ref);
 804  804  }
 805  805  
 806  806  /*
 807  807   * Return next address ID in list
 808  808   *
 809  809   * damapp:      address map handle
 810  810   * damap_list:  address ID list passed to config|unconfig
 811  811   *              returned by look by lookup_all
 812  812   * last:        last ID returned, 0 is start of list
 813  813   *
 814  814   * Returns:     addrid          Next ID from the list
 815  815   *              0               End of the list
 816  816   */
 817  817  damap_id_t
 818  818  damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
 819  819  {
 820  820          int i, start;
 821  821          dam_t *mapp = (dam_t *)damapp;
 822  822          bitset_t *dam_list = (bitset_t *)damap_list;
 823  823  
 824  824          if (!mapp || !dam_list)
 825  825                  return ((damap_id_t)0);
 826  826  
 827  827          start = (int)last + 1;
 828  828          for (i = start; i < mapp->dam_high; i++) {
 829  829                  if (bitset_in_set(dam_list, i)) {
 830  830                          return ((damap_id_t)i);
 831  831                  }
 832  832          }
 833  833          return ((damap_id_t)0);
 834  834  }
 835  835  
 836  836  /*
 837  837   * Set config private data
 838  838   *
 839  839   * damapp:      address map handle
 840  840   * addrid:      address ID
 841  841   * cfg_priv:    configuration private data
 842  842   *
 843  843   */
 844  844  void
 845  845  damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
 846  846  {
 847  847          dam_t *mapp = (dam_t *)damapp;
 848  848          dam_da_t *passp;
 849  849  
 850  850          mutex_enter(&mapp->dam_lock);
 851  851          passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
 852  852          if (!passp) {
 853  853                  mutex_exit(&mapp->dam_lock);
 854  854                  return;
 855  855          }
 856  856          passp->da_cfg_priv = cfg_priv;
 857  857          mutex_exit(&mapp->dam_lock);
 858  858  }
 859  859  
 860  860  /*
 861  861   * Get config private data
 862  862   *
 863  863   * damapp:      address map handle
 864  864   * addrid:      address ID
 865  865   *
 866  866   * Returns:     configuration private data
 867  867   */
 868  868  void *
 869  869  damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
 870  870  {
 871  871          dam_t *mapp = (dam_t *)damapp;
 872  872          dam_da_t *passp;
 873  873          void *rv;
 874  874  
 875  875          mutex_enter(&mapp->dam_lock);
 876  876          passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
 877  877          if (!passp) {
 878  878                  mutex_exit(&mapp->dam_lock);
 879  879                  return (NULL);
 880  880          }
 881  881          rv = passp->da_cfg_priv;
 882  882          mutex_exit(&mapp->dam_lock);
 883  883          return (rv);
 884  884  }
 885  885  
 886  886  /*
 887  887   * Lookup a single address in the active address map
 888  888   *
 889  889   * damapp:      address map handle
 890  890   * address:     address string
 891  891   *
 892  892   * Returns:     ID of active/stable address
 893  893   *              0       Address not in stable set
 894  894   *
 895  895   * Future: Allow the caller to wait for stabilize before returning not found.
 896  896   */
 897  897  damap_id_t
 898  898  damap_lookup(damap_t *damapp, char *address)
 899  899  {
 900  900          dam_t *mapp = (dam_t *)damapp;
 901  901          id_t addrid = 0;
 902  902          dam_da_t *passp = NULL;
 903  903  
 904  904          DTRACE_PROBE3(damap__lookup,
 905  905              char *, mapp->dam_name, dam_t *, mapp,
 906  906              char *, address);
 907  907          mutex_enter(&mapp->dam_lock);
 908  908          if (!mapp->dam_high)
 909  909                  addrid = 0;
 910  910          else
 911  911                  addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
 912  912          if (addrid) {
 913  913                  if (DAM_IS_STABLE(mapp, addrid)) {
 914  914                          passp = ddi_get_soft_state(mapp->dam_da, addrid);
 915  915                          ASSERT(passp);
 916  916                          if (passp) {
 917  917                                  passp->da_ref++;
 918  918                          } else {
 919  919                                  addrid = 0;
 920  920                          }
 921  921                  } else {
 922  922                          addrid = 0;
 923  923                  }
 924  924          }
 925  925          mutex_exit(&mapp->dam_lock);
 926  926          DTRACE_PROBE4(damap__lookup__return,
 927  927              char *, mapp->dam_name, dam_t *, mapp,
 928  928              char *, address, int, addrid);
 929  929          return ((damap_id_t)addrid);
 930  930  }
 931  931  
 932  932  
 933  933  /*
 934  934   * Return the list of stable addresses in the map
 935  935   *
 936  936   * damapp:      address map handle
 937  937   * id_listp:    pointer to list of address IDs in stable map (returned)
 938  938   *
 939  939   * Returns:     # of entries returned in alist
 940  940   */
 941  941  int
 942  942  damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
 943  943  {
 944  944          dam_t *mapp = (dam_t *)damapp;
 945  945          int mapsz = mapp->dam_size;
 946  946          int n_ids, i;
 947  947          bitset_t *bsp;
 948  948          char     *addrp;
 949  949          dam_da_t *passp;
 950  950  
 951  951          DTRACE_PROBE2(damap__lookup__all,
 952  952              char *, mapp->dam_name, dam_t *, mapp);
 953  953          mutex_enter(&mapp->dam_lock);
 954  954          if (!mapp->dam_high) {
 955  955                  *id_listp = (damap_id_list_t)NULL;
 956  956                  mutex_exit(&mapp->dam_lock);
 957  957                  DTRACE_PROBE2(damap__lookup__all__nomap,
 958  958                      char *, mapp->dam_name, dam_t *, mapp);
 959  959                  return (0);
 960  960          }
 961  961          bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
 962  962          bitset_init(bsp);
 963  963          bitset_resize(bsp, mapsz);
 964  964          bitset_copy(&mapp->dam_active_set, bsp);
 965  965          for (n_ids = 0, i = 1; i < mapsz; i++) {
 966  966                  if (bitset_in_set(bsp, i)) {
 967  967                          passp = ddi_get_soft_state(mapp->dam_da, i);
 968  968                          ASSERT(passp);
 969  969                          if (passp) {
 970  970                                  addrp = damap_id2addr(damapp, i);
 971  971                                  DTRACE_PROBE3(damap__lookup__all__item,
 972  972                                      char *, mapp->dam_name, dam_t *, mapp,
 973  973                                      char *, addrp);
 974  974                                  passp->da_ref++;
 975  975                                  n_ids++;
 976  976                          }
 977  977                  }
 978  978          }
 979  979          if (n_ids) {
 980  980                  *id_listp = (damap_id_list_t)bsp;
 981  981                  mutex_exit(&mapp->dam_lock);
 982  982                  return (n_ids);
 983  983          } else {
 984  984                  *id_listp = (damap_id_list_t)NULL;
 985  985                  bitset_fini(bsp);
 986  986                  kmem_free(bsp, sizeof (*bsp));
 987  987                  mutex_exit(&mapp->dam_lock);
 988  988                  return (0);
 989  989          }
 990  990  }
 991  991  
 992  992  /*
 993  993   * Release the address list returned by damap_lookup_all()
 994  994   *
 995  995   * mapp:        address map handle
 996  996   * id_list:     list of address IDs returned in damap_lookup_all()
 997  997   */
 998  998  void
 999  999  damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
1000 1000  {
1001 1001          dam_t *mapp = (dam_t *)damapp;
1002 1002          int i;
1003 1003  
1004 1004          if (id_list == NULL)
1005 1005                  return;
1006 1006  
1007 1007          mutex_enter(&mapp->dam_lock);
1008 1008          for (i = 1; i < mapp->dam_high; i++) {
1009 1009                  if (bitset_in_set((bitset_t *)id_list, i))
1010 1010                          (void) dam_addr_release(mapp, i);
1011 1011          }
1012 1012          mutex_exit(&mapp->dam_lock);
1013 1013          bitset_fini((bitset_t *)id_list);
1014 1014          kmem_free((void *)id_list, sizeof (bitset_t));
1015 1015  }
1016 1016  
1017 1017  /*
1018 1018   * activate an address that has passed the stabilization interval
1019 1019   */
1020 1020  static void
1021 1021  dam_addr_activate(dam_t *mapp, id_t addrid)
1022 1022  {
1023 1023          dam_da_t *passp;
1024 1024          int config_rv;
1025 1025          char *addrstr;
1026 1026  
1027 1027          mutex_enter(&mapp->dam_lock);
1028 1028          bitset_add(&mapp->dam_active_set, addrid);
1029 1029          passp = ddi_get_soft_state(mapp->dam_da, addrid);
1030 1030          ASSERT(passp);
1031 1031  
1032 1032          /*
1033 1033           * copy the reported nvlist and provider private data
1034 1034           */
1035 1035          addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1036 1036          DTRACE_PROBE3(damap__addr__activate__start,
1037 1037              char *, mapp->dam_name, dam_t *, mapp,
1038 1038              char *, addrstr);
1039 1039          passp->da_nvl = passp->da_nvl_rpt;
1040 1040          passp->da_ppriv = passp->da_ppriv_rpt;
1041 1041          passp->da_ppriv_rpt = NULL;
1042 1042          passp->da_nvl_rpt = NULL;
1043 1043          passp->da_last_stable = gethrtime();
1044 1044          passp->da_stable_cnt++;
1045 1045          mutex_exit(&mapp->dam_lock);
1046 1046          if (mapp->dam_activate_cb) {
1047 1047                  (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
1048 1048                      addrid, &passp->da_ppriv_rpt);
1049 1049          }
1050 1050  
1051 1051          /*
1052 1052           * call the address-specific configuration action as part of
1053 1053           * activation.
1054 1054           */
1055 1055          config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
1056 1056              addrid);
1057 1057          if (config_rv != DAM_SUCCESS) {
1058 1058                  mutex_enter(&mapp->dam_lock);
1059 1059                  passp->da_flags |= DA_FAILED_CONFIG;
1060 1060                  mutex_exit(&mapp->dam_lock);
1061 1061                  DTRACE_PROBE3(damap__addr__activate__config__failure,
1062 1062                      char *, mapp->dam_name, dam_t *, mapp,
1063 1063                      char *, addrstr);
1064 1064                  dam_deact_cleanup(mapp, addrid, addrstr,
1065 1065                      DAMAP_DEACT_RSN_CFG_FAIL);
1066 1066          } else {
1067 1067                  DTRACE_PROBE3(damap__addr__activate__end,
1068 1068                      char *, mapp->dam_name, dam_t *, mapp,
1069 1069                      char *, addrstr);
1070 1070          }
1071 1071  }
1072 1072  
1073 1073  /*
1074 1074   * deactivate a previously stable address
1075 1075   */
1076 1076  static void
1077 1077  dam_addr_deactivate(dam_t *mapp, id_t addrid)
1078 1078  {
1079 1079          char *addrstr;
1080 1080  
1081 1081          addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1082 1082          DTRACE_PROBE3(damap__addr__deactivate__start,
1083 1083              char *, mapp->dam_name, dam_t *, mapp,
1084 1084              char *, addrstr);
1085 1085  
1086 1086          /*
1087 1087           * call the unconfiguration callback
1088 1088           */
1089 1089          (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
1090 1090          dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
1091 1091  }
1092 1092  
1093 1093  static void
1094 1094  dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
1095 1095      damap_deact_rsn_t deact_rsn)
1096 1096  {
1097 1097          dam_da_t *passp;
1098 1098  
1099 1099          passp = ddi_get_soft_state(mapp->dam_da, addrid);
1100 1100          ASSERT(passp);
1101 1101          if (mapp->dam_deactivate_cb)
1102 1102                  (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1103 1103                      ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1104 1104                      addrid, passp->da_ppriv, deact_rsn);
1105 1105  
1106 1106          /*
1107 1107           * clear the active bit and free the backing info for
1108 1108           * this address
1109 1109           */
1110 1110          mutex_enter(&mapp->dam_lock);
1111 1111          bitset_del(&mapp->dam_active_set, addrid);
1112 1112          passp->da_ppriv = NULL;
1113 1113          if (passp->da_nvl)
1114 1114                  nvlist_free(passp->da_nvl);
1115 1115          passp->da_nvl = NULL;
1116 1116          passp->da_ppriv_rpt = NULL;
1117 1117          if (passp->da_nvl_rpt)
1118 1118                  nvlist_free(passp->da_nvl_rpt);
1119 1119          passp->da_nvl_rpt = NULL;
1120 1120  
1121 1121          DTRACE_PROBE3(damap__addr__deactivate__end,
1122 1122              char *, mapp->dam_name, dam_t *, mapp,
1123 1123              char *, addrstr);
1124 1124  
1125 1125          (void) dam_addr_release(mapp, addrid);
1126 1126          mutex_exit(&mapp->dam_lock);
1127 1127  }
1128 1128  
1129 1129  /*
1130 1130   * taskq callback for multi-thread activation
1131 1131   */
1132 1132  static void
1133 1133  dam_tq_config(void *arg)
1134 1134  {
1135 1135          cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1136 1136  
1137 1137          dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
1138 1138          kmem_free(tqd, sizeof (*tqd));
1139 1139  }
1140 1140  
1141 1141  /*
1142 1142   * taskq callback for multi-thread deactivation
1143 1143   */
1144 1144  static void
1145 1145  dam_tq_unconfig(void *arg)
1146 1146  {
1147 1147          cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1148 1148  
1149 1149          dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1150 1150          kmem_free(tqd, sizeof (*tqd));
1151 1151  }
1152 1152  
1153 1153  /*
1154 1154   * Activate a set of stabilized addresses
1155 1155   */
1156 1156  static void
1157 1157  dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1158 1158  {
1159 1159  
1160 1160          int i, nset;
1161 1161          taskq_t *tqp = NULL;
1162 1162          cfg_tqd_t *tqd = NULL;
1163 1163          char tqn[TASKQ_NAMELEN];
1164 1164          extern pri_t maxclsyspri;
1165 1165  
1166 1166          if (mapp->dam_options & DAMAP_MTCONFIG) {
1167 1167                  /*
1168 1168                   * calculate the # of taskq threads to create
1169 1169                   */
1170 1170                  for (i = 1, nset = 0; i < mapp->dam_high; i++)
1171 1171                          if (bitset_in_set(activate, i))
1172 1172                                  nset++;
1173 1173                  ASSERT(nset);
1174 1174                  (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1175 1175                  tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1176 1176                      INT_MAX, TASKQ_PREPOPULATE);
1177 1177          }
1178 1178          for (i = 1; i < mapp->dam_high; i++) {
1179 1179                  if (bitset_in_set(activate, i)) {
1180 1180                          if (!tqp)
1181 1181                                  dam_addr_activate(mapp, i);
1182 1182                          else {
1183 1183                                  /*
1184 1184                                   * multi-threaded activation
1185 1185                                   */
1186 1186                                  tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1187 1187                                  tqd->tqd_mapp = mapp;
1188 1188                                  tqd->tqd_id = i;
1189 1189                                  (void) taskq_dispatch(tqp, dam_tq_config,
1190 1190                                      tqd, TQ_SLEEP);
1191 1191                          }
1192 1192                  }
1193 1193          }
1194 1194          if (tqp) {
1195 1195                  taskq_wait(tqp);
1196 1196                  taskq_destroy(tqp);
1197 1197          }
1198 1198  }
1199 1199  
1200 1200  /*
1201 1201   * Deactivate a set of stabilized addresses
1202 1202   */
1203 1203  static void
1204 1204  dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1205 1205  {
1206 1206          int i, nset;
1207 1207          taskq_t *tqp = NULL;
1208 1208          cfg_tqd_t *tqd = NULL;
1209 1209          char tqn[TASKQ_NAMELEN];
1210 1210  
1211 1211          DTRACE_PROBE2(damap__addrset__deactivate,
1212 1212              char *, mapp->dam_name, dam_t *, mapp);
1213 1213  
1214 1214          if (mapp->dam_options & DAMAP_MTCONFIG) {
1215 1215                  /*
1216 1216                   * compute the # of taskq threads to dispatch
1217 1217                   */
1218 1218                  for (i = 1, nset = 0; i < mapp->dam_high; i++)
1219 1219                          if (bitset_in_set(deactivate, i))
1220 1220                                  nset++;
1221 1221                  (void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1222 1222                      mapp->dam_name);
1223 1223                  tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1224 1224                      INT_MAX, TASKQ_PREPOPULATE);
1225 1225          }
1226 1226          for (i = 1; i < mapp->dam_high; i++) {
1227 1227                  if (bitset_in_set(deactivate, i)) {
1228 1228                          if (!tqp) {
1229 1229                                  dam_addr_deactivate(mapp, i);
1230 1230                          } else {
1231 1231                                  tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1232 1232                                  tqd->tqd_mapp = mapp;
1233 1233                                  tqd->tqd_id = i;
1234 1234                                  (void) taskq_dispatch(tqp,
1235 1235                                      dam_tq_unconfig, tqd, TQ_SLEEP);
1236 1236                          }
1237 1237                  }
1238 1238          }
1239 1239  
1240 1240          if (tqp) {
1241 1241                  taskq_wait(tqp);
1242 1242                  taskq_destroy(tqp);
1243 1243          }
1244 1244  }
1245 1245  
1246 1246  /*
1247 1247   * Release a previously activated address
1248 1248   */
1249 1249  static void
1250 1250  dam_addr_release(dam_t *mapp, id_t addrid)
1251 1251  {
1252 1252          dam_da_t *passp;
1253 1253          char     *addrstr;
1254 1254  
1255 1255  
1256 1256          ASSERT(mutex_owned(&mapp->dam_lock));
1257 1257          passp = ddi_get_soft_state(mapp->dam_da, addrid);
1258 1258          ASSERT(passp);
1259 1259  
1260 1260          addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1261 1261          DTRACE_PROBE3(damap__addr__release,
1262 1262              char *, mapp->dam_name, dam_t *, mapp,
1263 1263              char *, addrstr);
1264 1264  
1265 1265          /*
1266 1266           * defer releasing the address until outstanding references
1267 1267           * are released
1268 1268           */
1269 1269          if (passp->da_ref > 1) {
1270 1270                  DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1271 1271                      char *, mapp->dam_name, dam_t *, mapp,
1272 1272                      char *, addrstr, int, passp->da_ref);
1273 1273                  return;
1274 1274          }
1275 1275  
1276 1276          /*
1277 1277           * allow pending reports to stabilize
1278 1278           */
1279 1279          if (DAM_IN_REPORT(mapp, addrid)) {
1280 1280                  DTRACE_PROBE3(damap__addr__release__report__pending,
1281 1281                      char *, mapp->dam_name, dam_t *, mapp,
1282 1282                      char *, addrstr);
1283 1283                  return;
1284 1284          }
1285 1285  
1286 1286          ddi_strid_free(mapp->dam_addr_hash, addrid);
1287 1287          ddi_soft_state_free(mapp->dam_da, addrid);
1288 1288  }
1289 1289  
1290 1290  /*
1291 1291   * process stabilized address reports
1292 1292   */
1293 1293  static void
1294 1294  dam_stabilize_map(void *arg)
1295 1295  {
1296 1296          dam_t *mapp = (dam_t *)arg;
1297 1297          bitset_t delta;
1298 1298          bitset_t cfg;
1299 1299          bitset_t uncfg;
1300 1300          int has_cfg, has_uncfg;
1301 1301          uint32_t i, n_active;
1302 1302  
1303 1303          DTRACE_PROBE2(damap__stabilize__map,
1304 1304              char *, mapp->dam_name, dam_t *, mapp);
1305 1305  
1306 1306          bitset_init(&delta);
1307 1307          bitset_resize(&delta, mapp->dam_size);
1308 1308          bitset_init(&cfg);
1309 1309          bitset_resize(&cfg, mapp->dam_size);
1310 1310          bitset_init(&uncfg);
1311 1311          bitset_resize(&uncfg, mapp->dam_size);
1312 1312  
1313 1313          /*
1314 1314           * determine which addresses have changed during
1315 1315           * this stabilization cycle
1316 1316           */
1317 1317          mutex_enter(&mapp->dam_lock);
1318 1318          ASSERT(mapp->dam_flags & DAM_SPEND);
1319 1319          if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
1320 1320              &delta)) {
1321 1321                  /*
1322 1322                   * no difference
1323 1323                   */
1324 1324                  bitset_zero(&mapp->dam_stable_set);
1325 1325                  mapp->dam_flags &= ~DAM_SPEND;
1326 1326                  cv_signal(&mapp->dam_sync_cv);
1327 1327                  mutex_exit(&mapp->dam_lock);
1328 1328  
1329 1329                  bitset_fini(&uncfg);
1330 1330                  bitset_fini(&cfg);
1331 1331                  bitset_fini(&delta);
1332 1332                  DTRACE_PROBE2(damap__stabilize__map__nochange,
1333 1333                      char *, mapp->dam_name, dam_t *, mapp);
1334 1334                  return;
1335 1335          }
1336 1336  
1337 1337          /*
1338 1338           * compute the sets of addresses to be activated and deactivated
1339 1339           */
1340 1340          has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
1341 1341          has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1342 1342  
1343 1343          /*
1344 1344           * drop map lock while invoking callouts
1345 1345           */
1346 1346          mutex_exit(&mapp->dam_lock);
1347 1347  
1348 1348          /*
1349 1349           * activate all newly stable addresss
1350 1350           */
1351 1351          if (has_cfg)
1352 1352                  dam_addrset_activate(mapp, &cfg);
1353 1353  
1354 1354          /*
1355 1355           * deactivate addresss which are no longer in the map
1356 1356           */
1357 1357          if (has_uncfg)
1358 1358                  dam_addrset_deactivate(mapp, &uncfg);
1359 1359  
1360 1360  
1361 1361          /*
1362 1362           * timestamp the last stable time and increment the kstat keeping
1363 1363           * the # of of stable cycles for the map
1364 1364           */
1365 1365          mutex_enter(&mapp->dam_lock);
1366 1366          bitset_zero(&mapp->dam_stable_set);
1367 1367          mapp->dam_last_stable = gethrtime();
1368 1368          mapp->dam_stable_cnt++;
1369 1369          DAM_INCR_STAT(mapp, dam_cycles);
1370 1370  
1371 1371          /*
1372 1372           * determine the number of stable addresses
1373 1373           * and update the n_active kstat for this map
1374 1374           */
1375 1375          for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1376 1376                  if (bitset_in_set(&mapp->dam_active_set, i))
1377 1377                          n_active++;
1378 1378          DAM_SET_STAT(mapp, dam_active, n_active);
1379 1379  
1380 1380          DTRACE_PROBE3(damap__map__stable__end,
1381 1381              char *, mapp->dam_name, dam_t *, mapp,
1382 1382              int, n_active);
1383 1383  
1384 1384          mapp->dam_flags &= ~DAM_SPEND;
1385 1385          cv_signal(&mapp->dam_sync_cv);
1386 1386          mutex_exit(&mapp->dam_lock);
1387 1387  
1388 1388          bitset_fini(&uncfg);
1389 1389          bitset_fini(&cfg);
1390 1390          bitset_fini(&delta);
1391 1391  }
1392 1392  
1393 1393  /*
1394 1394   * per-address stabilization timeout
1395 1395   */
1396 1396  static void
1397 1397  dam_addr_stable_cb(void *arg)
1398 1398  {
1399 1399          dam_t *mapp = (dam_t *)arg;
1400 1400          int i;
1401 1401          dam_da_t *passp;
1402 1402          int spend = 0;
1403 1403          int tpend = 0;
1404 1404          int64_t ts, next_ticks, delta_ticks;
1405 1405  
1406 1406          mutex_enter(&mapp->dam_lock);
1407 1407          if (mapp->dam_tid == 0) {
1408 1408                  DTRACE_PROBE2(damap__map__addr__stable__cancelled,
1409 1409                      char *, mapp->dam_name, dam_t *, mapp);
1410 1410                  mutex_exit(&mapp->dam_lock);
1411 1411                  return;
1412 1412          }
1413 1413          mapp->dam_tid = 0;
1414 1414  
1415 1415          /*
1416 1416           * If still under stabilization, reschedule timeout,
1417 1417           * otherwise dispatch the task to activate and deactivate the
1418 1418           * new stable address
1419 1419           */
1420 1420          if (mapp->dam_flags & DAM_SPEND) {
1421 1421                  DAM_INCR_STAT(mapp, dam_overrun);
1422 1422                  mapp->dam_stable_overrun++;
1423 1423                  DTRACE_PROBE2(damap__map__addr__stable__overrun,
1424 1424                      char *, mapp->dam_name, dam_t *, mapp);
1425 1425                  dam_sched_timeout(dam_addr_stable_cb, mapp,
1426 1426                      mapp->dam_stable_ticks);
1427 1427                  mutex_exit(&mapp->dam_lock);
1428 1428                  return;
1429 1429          }
1430 1430  
1431 1431          DAM_SET_STAT(mapp, dam_overrun, 0);
1432 1432          mapp->dam_stable_overrun = 0;
1433 1433  
1434 1434          /* See if any reports stabalized and compute next timeout. */
1435 1435          ts = ddi_get_lbolt64();
1436 1436          next_ticks = mapp->dam_stable_ticks;
1437 1437          for (i = 1; i < mapp->dam_high; i++) {
1438 1438                  if (bitset_in_set(&mapp->dam_report_set, i)) {
1439 1439                          passp = ddi_get_soft_state(mapp->dam_da, i);
1440 1440                          ASSERT(passp);
1441 1441  
1442 1442                          if (passp->da_deadline <= ts)
1443 1443                                  spend++;        /* report has stabilized */
1444 1444                          else {
1445 1445                                  /* not stabilized, determine next map timeout */
1446 1446                                  tpend++;
1447 1447                                  delta_ticks = passp->da_deadline - ts;
1448 1448                                  if (delta_ticks < next_ticks)
1449 1449                                          next_ticks = delta_ticks;
1450 1450                          }
1451 1451                  }
1452 1452          }
1453 1453  
1454 1454          /*
1455 1455           * schedule system_taskq activation of stabilized reports
1456 1456           */
1457 1457          if (spend) {
1458 1458                  if (taskq_dispatch(system_taskq, dam_stabilize_map,
1459 1459                      mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1460 1460                          DTRACE_PROBE2(damap__map__addr__stable__start,
1461 1461                              char *, mapp->dam_name, dam_t *, mapp);
1462 1462  
1463 1463                          /*
1464 1464                           * The stable_set we compute below stays pending until
1465 1465                           * processed by dam_stabilize_map. We can't set
1466 1466                           * DAM_SPEND (or bitset_del things from the
1467 1467                           * report_set) until we *know* that we can handoff the
1468 1468                           * result to dam_stabilize_map. If dam_stabilize_map
1469 1469                           * starts executing before we are complete, it will
1470 1470                           * block on the dam_lock mutex until we are ready.
1471 1471                           */
1472 1472                          mapp->dam_flags |= DAM_SPEND;
1473 1473  
1474 1474                          /*
1475 1475                           * Copy the current active_set to the stable_set, then
1476 1476                           * add or remove stabilized report_set address from
1477 1477                           * the stable set (and delete them from the report_set).
1478 1478                           */
1479 1479                          bitset_copy(&mapp->dam_active_set,
1480 1480                              &mapp->dam_stable_set);
1481 1481                          for (i = 1; i < mapp->dam_high; i++) {
1482 1482                                  if (!bitset_in_set(&mapp->dam_report_set, i))
1483 1483                                          continue;
1484 1484  
1485 1485                                  passp = ddi_get_soft_state(mapp->dam_da, i);
1486 1486                                  if (passp->da_deadline > ts)
1487 1487                                          continue; /* report not stabilized */
1488 1488  
1489 1489                                  /* report has stabilized */
1490 1490                                  if (passp->da_flags & DA_RELE)
1491 1491                                          bitset_del(&mapp->dam_stable_set, i);
1492 1492                                  else
1493 1493                                          bitset_add(&mapp->dam_stable_set, i);
1494 1494  
1495 1495                                  bitset_del(&mapp->dam_report_set, i);
1496 1496                          }
1497 1497                  } else {
1498 1498                          DTRACE_PROBE2(damap__map__addr__stable__spendfail,
1499 1499                              char *, mapp->dam_name, dam_t *, mapp);
1500 1500  
1501 1501                          /*
1502 1502                           * Avoid waiting the entire stabalization
1503 1503                           * time again if taskq_diskpatch fails.
1504 1504                           */
1505 1505                          tpend++;
1506 1506                          delta_ticks = drv_usectohz(
1507 1507                              damap_taskq_dispatch_retry_usec);
1508 1508                          if (delta_ticks < next_ticks)
1509 1509                                  next_ticks = delta_ticks;
1510 1510                  }
1511 1511          }
1512 1512  
1513 1513          /*
1514 1514           * reschedule the stabilization timer if there are reports
1515 1515           * still pending
1516 1516           */
1517 1517          if (tpend) {
1518 1518                  DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
1519 1519                      mapp->dam_name, dam_t *, mapp);
1520 1520                  dam_sched_timeout(dam_addr_stable_cb, mapp,
1521 1521                      (clock_t)next_ticks);
1522 1522          }
1523 1523  
1524 1524          mutex_exit(&mapp->dam_lock);
1525 1525  }
1526 1526  
1527 1527  /*
1528 1528   * fullset stabilization timeout callback
1529 1529   */
1530 1530  static void
1531 1531  dam_addrset_stable_cb(void *arg)
1532 1532  {
1533 1533          dam_t *mapp = (dam_t *)arg;
1534 1534  
1535 1535          mutex_enter(&mapp->dam_lock);
1536 1536          if (mapp->dam_tid == 0) {
1537 1537                  mutex_exit(&mapp->dam_lock);
1538 1538                  DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1539 1539                      char *, mapp->dam_name, dam_t *, mapp);
1540 1540                  return;
1541 1541          }
1542 1542          mapp->dam_tid = 0;
1543 1543  
1544 1544          /*
1545 1545           * If map still underoing stabilization reschedule timeout,
1546 1546           * else dispatch the task to configure the new stable set of
1547 1547           * addresses.
1548 1548           */
1549 1549          if ((mapp->dam_flags & DAM_SPEND) ||
1550 1550              (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1551 1551              TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
1552 1552                  DAM_INCR_STAT(mapp, dam_overrun);
1553 1553                  mapp->dam_stable_overrun++;
1554 1554                  dam_sched_timeout(dam_addrset_stable_cb, mapp,
1555 1555                      drv_usectohz(damap_taskq_dispatch_retry_usec));
1556 1556  
1557 1557                  DTRACE_PROBE2(damap__map__addrset__stable__overrun,
1558 1558                      char *, mapp->dam_name, dam_t *, mapp);
1559 1559                  mutex_exit(&mapp->dam_lock);
1560 1560                  return;
1561 1561          }
1562 1562  
1563 1563          DAM_SET_STAT(mapp, dam_overrun, 0);
1564 1564          mapp->dam_stable_overrun = 0;
1565 1565          bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1566 1566          bitset_zero(&mapp->dam_report_set);
1567 1567          mapp->dam_flags |= DAM_SPEND;
1568 1568          mapp->dam_flags &= ~DAM_SETADD;
1569 1569          /* NOTE: don't need cv_signal since DAM_SPEND is still set */
1570 1570  
1571 1571          DTRACE_PROBE2(damap__map__addrset__stable__start,
1572 1572              char *, mapp->dam_name, dam_t *, mapp);
1573 1573          mutex_exit(&mapp->dam_lock);
1574 1574  }
1575 1575  
1576 1576  /*
1577 1577   * schedule map timeout in 'ticks' ticks
1578 1578   * if map timer is currently running, cancel if ticks == 0
1579 1579   */
1580 1580  static void
1581 1581  dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
1582 1582  {
1583 1583          timeout_id_t tid;
1584 1584  
1585 1585          DTRACE_PROBE4(damap__sched__timeout,
1586 1586              char *, mapp->dam_name, dam_t *, mapp,
1587 1587              int, ticks, timeout_id_t, mapp->dam_tid);
1588 1588  
1589 1589          ASSERT(mutex_owned(&mapp->dam_lock));
1590 1590          if ((tid = mapp->dam_tid) != 0) {
1591 1591                  if (ticks == 0) {
1592 1592                          mapp->dam_tid = 0;
1593 1593                          mutex_exit(&mapp->dam_lock);
1594 1594                          (void) untimeout(tid);
1595 1595                          mutex_enter(&mapp->dam_lock);
1596 1596                  }
1597 1597          } else {
1598 1598                  if (timeout_cb && (ticks != 0))
1599 1599                          mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
1600 1600          }
1601 1601  }
1602 1602  
1603 1603  /*
1604 1604   * report addition or removal of an address
1605 1605   */
1606 1606  static void
1607 1607  dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
1608 1608  {
1609 1609          char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1610 1610  
1611 1611          DTRACE_PROBE4(damap__addr__report,
1612 1612              char *, mapp->dam_name, dam_t *, mapp,
1613 1613              char *, addrstr, int, rpt_type);
1614 1614  
1615 1615          ASSERT(mutex_owned(&mapp->dam_lock));
1616 1616          ASSERT(!DAM_IN_REPORT(mapp, addrid));
1617 1617          passp->da_last_report = gethrtime();
1618 1618          mapp->dam_last_update = gethrtime();
1619 1619          passp->da_report_cnt++;
1620 1620          passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
1621 1621          if (rpt_type == RPT_ADDR_DEL)
1622 1622                  passp->da_flags |= DA_RELE;
1623 1623          else if (rpt_type == RPT_ADDR_ADD)
1624 1624                  passp->da_flags &= ~DA_RELE;
1625 1625          bitset_add(&mapp->dam_report_set, addrid);
1626 1626          dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
1627 1627  }
1628 1628  
1629 1629  /*
1630 1630   * release an address report
1631 1631   */
1632 1632  static void
1633 1633  dam_addr_report_release(dam_t *mapp, id_t addrid)
1634 1634  {
1635 1635          dam_da_t *passp;
1636 1636          char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1637 1637  
1638 1638          DTRACE_PROBE3(damap__addr__report__release,
1639 1639              char *, mapp->dam_name, dam_t *, mapp,
1640 1640              char *, addrstr);
1641 1641  
1642 1642          ASSERT(mutex_owned(&mapp->dam_lock));
1643 1643          passp = ddi_get_soft_state(mapp->dam_da, addrid);
1644 1644          ASSERT(passp);
1645 1645          /*
1646 1646           * clear the report bit
1647 1647           * if the address has a registered deactivation handler and
1648 1648           * we are holding a private data pointer and the address has not
1649 1649           * stabilized, deactivate the address (private data).
1650 1650           */
1651 1651          bitset_del(&mapp->dam_report_set, addrid);
1652 1652          if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1653 1653              passp->da_ppriv_rpt) {
1654 1654                  mutex_exit(&mapp->dam_lock);
1655 1655                  (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1656 1656                      ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1657 1657                      addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
1658 1658                  mutex_enter(&mapp->dam_lock);
1659 1659          }
1660 1660          passp->da_ppriv_rpt = NULL;
1661 1661          if (passp->da_nvl_rpt)
1662 1662                  nvlist_free(passp->da_nvl_rpt);
1663 1663  }
1664 1664  
1665 1665  /*
1666 1666   * return the map ID of an address
1667 1667   */
1668 1668  static id_t
1669 1669  dam_get_addrid(dam_t *mapp, char *address)
1670 1670  {
1671 1671          damap_id_t addrid;
1672 1672          dam_da_t *passp;
1673 1673  
1674 1674          ASSERT(mutex_owned(&mapp->dam_lock));
1675 1675          if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1676 1676                  if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
1677 1677                      address)) == (damap_id_t)0) {
1678 1678                          return (0);
1679 1679                  }
1680 1680                  if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1681 1681                      DDI_SUCCESS) {
1682 1682                          ddi_strid_free(mapp->dam_addr_hash, addrid);
1683 1683                          return (0);
1684 1684                  }
1685 1685  
1686 1686                  if (addrid >= mapp->dam_high)
1687 1687                          mapp->dam_high = addrid + 1;
1688 1688  
1689 1689                  /*
1690 1690                   * expand bitmaps if ID has outgrown old map size
1691 1691                   */
1692 1692                  if (mapp->dam_high > mapp->dam_size) {
1693 1693                          mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1694 1694                          bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1695 1695                          bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1696 1696                          bitset_resize(&mapp->dam_report_set, mapp->dam_size);
1697 1697                  }
1698 1698  
1699 1699                  passp = ddi_get_soft_state(mapp->dam_da, addrid);
1700 1700                  passp->da_ref = 1;
1701 1701                  passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1702 1702                      addrid); /* for mdb */
1703 1703          }
1704 1704          return (addrid);
1705 1705  }
1706 1706  
1707 1707  /*
1708 1708   * create and install map statistics
1709 1709   */
1710 1710  static int
1711 1711  dam_kstat_create(dam_t *mapp)
1712 1712  {
1713 1713          kstat_t                 *mapsp;
1714 1714          struct dam_kstats       *statsp;
1715 1715  
1716 1716          mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1717 1717              KSTAT_TYPE_NAMED,
1718 1718              sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1719 1719  
1720 1720          if (mapsp == NULL)
1721 1721                  return (DDI_FAILURE);
1722 1722  
1723 1723          statsp = (struct dam_kstats *)mapsp->ks_data;
1724 1724          kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1725 1725          kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1726 1726          kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1727 1727          kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
1728 1728          kstat_install(mapsp);
1729 1729          mapp->dam_kstatsp = mapsp;
1730 1730          return (DDI_SUCCESS);
1731 1731  }
  
    | ↓ open down ↓ | 1684 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX