Author: hselasky
Date: Fri Aug 10 15:02:49 2012
New Revision: 239178
URL: http://svn.freebsd.org/changeset/base/239178

Log:
  Add new device method to free the automatically
  allocated softc structure which is returned by
  device_get_softc(). This method can be used to
  easily implement softc refcounting. This can be
  desirable when the softc has memory references
  which are controlled by userspace handles for
  example.
  
  This solves the problem of blocking the caller
  of device_detach() for a non-deterministic time.
  
  Discussed with:       kib, ed
  MFC after:    2 weeks

Modified:
  head/sys/kern/device_if.m
  head/sys/kern/subr_bus.c
  head/sys/sys/bus.h

Modified: head/sys/kern/device_if.m
==============================================================================
--- head/sys/kern/device_if.m   Fri Aug 10 14:51:41 2012        (r239177)
+++ head/sys/kern/device_if.m   Fri Aug 10 15:02:49 2012        (r239178)
@@ -316,3 +316,14 @@ METHOD int resume {
 METHOD int quiesce {
        device_t dev;
 } DEFAULT null_quiesce;
+
+/**
+ * @brief Free the device softc
+ *
+ * @param _dev         device pointer
+ * @param _softc       pointer to softc
+ */
+METHOD void free_softc {
+       device_t        _dev;
+       void            *_softc;
+} DEFAULT device_free_softc;

Modified: head/sys/kern/subr_bus.c
==============================================================================
--- head/sys/kern/subr_bus.c    Fri Aug 10 14:51:41 2012        (r239177)
+++ head/sys/kern/subr_bus.c    Fri Aug 10 15:02:49 2012        (r239178)
@@ -2406,8 +2406,8 @@ device_get_softc(device_t dev)
 void
 device_set_softc(device_t dev, void *softc)
 {
-       if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC))
-               free(dev->softc, M_BUS_SC);
+       if (dev->softc != NULL && !(dev->flags & DF_EXTERNALSOFTC))
+               DEVICE_FREE_SOFTC(dev, dev->softc);
        dev->softc = softc;
        if (dev->softc)
                dev->flags |= DF_EXTERNALSOFTC;
@@ -2604,8 +2604,8 @@ device_set_driver(device_t dev, driver_t
        if (dev->driver == driver)
                return (0);
 
-       if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) {
-               free(dev->softc, M_BUS_SC);
+       if (dev->softc != NULL && !(dev->flags & DF_EXTERNALSOFTC)) {
+               DEVICE_FREE_SOFTC(dev, dev->softc);
                dev->softc = NULL;
        }
        device_set_desc(dev, NULL);
@@ -4797,3 +4797,13 @@ bus_free_resource(device_t dev, int type
                return (0);
        return (bus_release_resource(dev, type, rman_get_rid(r), r));
 }
+
+/*
+ * The "dev" argument passed to "device_free_softc()" is allowed to be
+ * NULL, if the device freeing the soft is not available.
+ */
+void
+device_free_softc(device_t dev, void *softc)
+{
+       free(softc, M_BUS_SC);
+}

Modified: head/sys/sys/bus.h
==============================================================================
--- head/sys/sys/bus.h  Fri Aug 10 14:51:41 2012        (r239177)
+++ head/sys/sys/bus.h  Fri Aug 10 15:02:49 2012        (r239178)
@@ -468,6 +468,7 @@ int device_set_unit(device_t dev, int un
 int    device_shutdown(device_t dev);
 void   device_unbusy(device_t dev);
 void   device_verbose(device_t dev);
+void   device_free_softc(device_t dev, void *softc);
 
 /*
  * Access functions for devclass.
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to