Author: landonf
Date: Tue Aug 16 21:20:05 2016
New Revision: 304242
URL: https://svnweb.freebsd.org/changeset/base/304242

Log:
  bhndb(4): Drop MIPS-incompatible __builtin_ctz dependency.
  
  This replaces the bitfield representation of the bhndb register window
  freelist with the bitstring API, eliminating a dependency on
  (MIPS-unsupported) __builtin_ctz().
  
  Approved by:  adrian (mentor)
  Differential Revision:        https://reviews.freebsd.org/D7495

Modified:
  head/sys/dev/bhnd/bhndb/bhndb_private.h
  head/sys/dev/bhnd/bhndb/bhndb_subr.c

Modified: head/sys/dev/bhnd/bhndb/bhndb_private.h
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_private.h     Tue Aug 16 21:17:51 2016        
(r304241)
+++ head/sys/dev/bhnd/bhndb/bhndb_private.h     Tue Aug 16 21:20:05 2016        
(r304242)
@@ -33,6 +33,7 @@
 #define _BHND_BHNDB_PRIVATE_H_
 
 #include <sys/param.h>
+#include <sys/bitstring.h>
 #include <sys/bus.h>
 #include <sys/systm.h>
 
@@ -184,21 +185,23 @@ struct bhndb_resources {
 
        struct bhndb_dw_alloc           *dw_alloc;      /**< dynamic window 
allocation records */
        size_t                           dwa_count;     /**< number of dynamic 
windows available. */
-       uint32_t                         dwa_freelist;  /**< dynamic window 
free list */
+       bitstr_t                        *dwa_freelist;  /**< dynamic window 
free list */
        bhndb_priority_t                 min_prio;      /**< minimum resource 
priority required to
                                                             allocate a dynamic 
window */
 };
 
 /**
- * Returns true if the all dynamic windows have been exhausted, false
+ * Returns true if the all dynamic windows are marked free, false
  * otherwise.
  * 
  * @param br The resource state to check.
  */
 static inline bool
-bhndb_dw_exhausted(struct bhndb_resources *br)
+bhndb_dw_all_free(struct bhndb_resources *br)
 {
-       return (br->dwa_freelist == 0);
+       int bit;
+       bit_ffs(br->dwa_freelist, br->dwa_count, &bit);
+       return (bit == -1);
 }
 
 /**
@@ -209,12 +212,14 @@ bhndb_dw_exhausted(struct bhndb_resource
 static inline struct bhndb_dw_alloc *
 bhndb_dw_next_free(struct bhndb_resources *br)
 {
-       struct bhndb_dw_alloc *dw_free;
+       struct bhndb_dw_alloc   *dw_free;
+       int                      bit;
 
-       if (bhndb_dw_exhausted(br))
+       bit_ffc(br->dwa_freelist, br->dwa_count, &bit);
+       if (bit == -1)
                return (NULL);
 
-       dw_free = &br->dw_alloc[__builtin_ctz(br->dwa_freelist)];
+       dw_free = &br->dw_alloc[bit];
 
        KASSERT(LIST_EMPTY(&dw_free->refs),
            ("free list out of sync with refs"));
@@ -233,7 +238,7 @@ bhndb_dw_is_free(struct bhndb_resources 
 {
        bool is_free = LIST_EMPTY(&dwa->refs);
 
-       KASSERT(is_free == ((br->dwa_freelist & (1 << dwa->rnid)) != 0),
+       KASSERT(is_free == !bit_test(br->dwa_freelist, dwa->rnid),
            ("refs out of sync with free list"));
 
        return (is_free);

Modified: head/sys/dev/bhnd/bhndb/bhndb_subr.c
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_subr.c        Tue Aug 16 21:17:51 2016        
(r304241)
+++ head/sys/dev/bhnd/bhndb/bhndb_subr.c        Tue Aug 16 21:20:05 2016        
(r304242)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/limits.h>
 
 #include "bhndb_private.h"
 #include "bhndbvar.h"
@@ -264,7 +265,7 @@ bhndb_alloc_resources(device_t dev, devi
        const struct bhndb_regwin       *win;
        bus_size_t                       last_window_size;
        size_t                           res_num;
-       u_int                            rnid;
+       int                              rnid;
        int                              error;
        bool                             free_parent_res;
        bool                             free_ht_mem, free_br_mem;
@@ -371,10 +372,10 @@ bhndb_alloc_resources(device_t dev, devi
        }
 
        /* Fetch the dynamic regwin count and verify that it does not exceed
-        * what is representable via our freelist bitmask. */
+        * what is representable via our freelist bitstring. */
        r->dwa_count = bhndb_regwin_count(cfg->register_windows,
            BHNDB_REGWIN_T_DYN);
-       if (r->dwa_count >= (8 * sizeof(r->dwa_freelist))) {
+       if (r->dwa_count >= INT_MAX) {
                device_printf(r->dev, "max dynamic regwin count exceeded\n");
                goto failed;
        }
@@ -385,8 +386,12 @@ bhndb_alloc_resources(device_t dev, devi
        if (r->dw_alloc == NULL)
                goto failed;
 
-       /* Initialize the dynamic window table and freelist. */
-       r->dwa_freelist = 0;
+       /* Allocate the dynamic window allocation freelist */
+       r->dwa_freelist = bit_alloc(r->dwa_count, M_BHND, M_NOWAIT);
+       if (r->dwa_freelist == NULL)
+               goto failed;
+
+       /* Initialize the dynamic window table */
        rnid = 0;
        last_window_size = 0;
        for (win = cfg->register_windows;
@@ -446,9 +451,6 @@ bhndb_alloc_resources(device_t dev, devi
                        goto failed;
                }
 
-               /* Add to freelist */
-               r->dwa_freelist |= (1 << rnid);
-
                rnid++;
        }
 
@@ -473,6 +475,9 @@ failed:
        if (r->dw_alloc != NULL)
                free(r->dw_alloc, M_BHND);
 
+       if (r->dwa_freelist != NULL)
+               free(r->dwa_freelist, M_BHND);
+
        free (r, M_BHND);
 
        return (NULL);
@@ -491,9 +496,17 @@ bhndb_free_resources(struct bhndb_resour
        struct bhndb_dw_rentry  *dwr, *dwr_next;
 
        /* No window regions may still be held */
-       if (__builtin_popcount(br->dwa_freelist) != br->dwa_count) {
-               device_printf(br->dev, "leaked %llu dynamic register regions\n",
-                   (unsigned long long) br->dwa_count - br->dwa_freelist);
+       if (!bhndb_dw_all_free(br)) {
+               for (int i = 0; i < br->dwa_count; i++) {
+                       dwa = &br->dw_alloc[i];
+
+                       /* Skip free dynamic windows */
+                       if (bhndb_dw_is_free(br, dwa))
+                               continue;
+
+                       device_printf(br->dev,
+                           "leaked dynamic register window %d\n", dwa->rnid);
+               }
        }
 
        /* Release resources allocated through our parent. */
@@ -523,6 +536,7 @@ bhndb_free_resources(struct bhndb_resour
        free(br->res, M_BHND);
        free(br->res_spec, M_BHND);
        free(br->dw_alloc, M_BHND);
+       free(br->dwa_freelist, M_BHND);
 }
 
 /**
@@ -765,7 +779,7 @@ bhndb_dw_retain(struct bhndb_resources *
        LIST_INSERT_HEAD(&dwa->refs, rentry, dw_link);
 
        /* Update the free list */
-       br->dwa_freelist &= ~(1 << (dwa->rnid));
+       bit_set(br->dwa_freelist, dwa->rnid);
  
        return (0);
 }
@@ -794,7 +808,7 @@ bhndb_dw_release(struct bhndb_resources 
 
        /* If this was the last reference, update the free list */
        if (LIST_EMPTY(&dwa->refs))
-               br->dwa_freelist |= (1 << (dwa->rnid));
+               bit_clear(br->dwa_freelist, dwa->rnid);
 }
 
 /**
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to