[svn-commits] tzafrir: linux/trunk r8900 - /linux/trunk/drivers/dahdi/xpp/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Jul 13 10:10:34 CDT 2010


Author: tzafrir
Date: Tue Jul 13 10:10:30 2010
New Revision: 8900

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=8900
Log:
Keep SYSFS objects after disconnect

* Astribanks no longer live directly under the USB devices in the device tree.
* The 'transport' link does point there as before, however.
* When the USB device disconnects, we keep references to them to make sure
  they don't disappear.

Modified:
    linux/trunk/drivers/dahdi/xpp/xbus-core.c
    linux/trunk/drivers/dahdi/xpp/xbus-core.h
    linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c
    linux/trunk/drivers/dahdi/xpp/xpd.h
    linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c

Modified: linux/trunk/drivers/dahdi/xpp/xbus-core.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xbus-core.c?view=diff&rev=8900&r1=8899&r2=8900
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xbus-core.c (original)
+++ linux/trunk/drivers/dahdi/xpp/xbus-core.c Tue Jul 13 10:10:30 2010
@@ -141,28 +141,36 @@
 	}
 }
 
+/*
+ * Called by put_xbus() when XBUS has no more references.
+ */
+static void xbus_destroy(struct kref *kref)
+{
+	xbus_t	*xbus;
+
+	xbus = kref_to_xbus(kref);
+	XBUS_NOTICE(xbus, "%s\n", __func__);
+	xbus_sysfs_remove(xbus);
+}
+
 xbus_t *get_xbus(const char *msg, xbus_t *xbus)
 {
-	struct device	*dev;
-
 	XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n",
 		msg, refcount_xbus(xbus));
-	dev = get_device(&xbus->astribank);
-	if (!dev)
-		return NULL;
-	return dev_to_xbus(dev);
+	kref_get(&xbus->kref);
+	return xbus;
 }
 
 void put_xbus(const char *msg, xbus_t *xbus)
 {
 	XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n",
 		msg, refcount_xbus(xbus));
-	put_device(&xbus->astribank);
+	kref_put(&xbus->kref, xbus_destroy);
 }
 
 int refcount_xbus(xbus_t *xbus)
 {
-	struct kref *kref = &xbus->astribank.kobj.kref;
+	struct kref *kref = &xbus->kref;
 
 	return atomic_read(&kref->refcount);
 }
@@ -1049,7 +1057,6 @@
 
 	BUG_ON(!xbus);
 	worker = &xbus->worker;
-	xbus = container_of(worker, xbus_t, worker);
 	name = (xbus) ? xbus->busname : "detached";
 	DBG(DEVICES, "%s\n", name);
 	if(!worker->xpds_init_done) {
@@ -1300,7 +1307,7 @@
 	xbus_command_queue_waitempty(xbus);
 	xbus_setstate(xbus, XBUS_STATE_DEACTIVATED);
 	worker_reset(xbus);
-	xbus_release_xpds(xbus);	/* taken in xpd_device_register() */
+	xbus_release_xpds(xbus);	/* taken in xpd_alloc() [kref_init] */
 	elect_syncer("deactivate");
 }
 
@@ -1323,7 +1330,8 @@
 	worker_destroy(xbus);
 	XBUS_DBG(DEVICES, xbus, "Deactivated refcount_xbus=%d\n",
 		refcount_xbus(xbus));
-	xbus_sysfs_remove(xbus);	/* Device-Model */
+	xbus_sysfs_transport_remove(xbus);	/* Device-Model */
+	put_xbus(__func__, xbus);	/* from xbus_new() [kref_init()] */
 }
 
 static xbus_t *xbus_alloc(void)
@@ -1427,12 +1435,19 @@
 	xbus->min_tx_sync = INT_MAX;
 	xbus->min_rx_sync = INT_MAX;
 	
+	kref_init(&xbus->kref);
 	worker_init(xbus);
 	atomic_set(&xbus->num_xpds, 0);
 	xbus->sync_mode = SYNC_MODE_NONE;
 	err = xbus_sysfs_create(xbus);
 	if(err) {
 		XBUS_ERR(xbus, "SYSFS creation failed: %d\n", err);
+		goto nobus;
+	}
+	err = xbus_sysfs_transport_create(xbus);
+	if (err) {
+		XBUS_ERR(xbus, "SYSFS transport link creation failed: %d\n",
+				err);
 		goto nobus;
 	}
 	xbus_reset_counters(xbus);

Modified: linux/trunk/drivers/dahdi/xpp/xbus-core.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xbus-core.h?view=diff&rev=8900&r1=8899&r2=8900
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xbus-core.h (original)
+++ linux/trunk/drivers/dahdi/xpp/xbus-core.h Tue Jul 13 10:10:30 2010
@@ -24,6 +24,7 @@
 
 #include <linux/wait.h>
 #include <linux/interrupt.h>	/* for tasklets */
+#include <linux/kref.h>
 #include "xpd.h"
 #include "xframe_queue.h"
 #include "xbus-pcm.h"
@@ -206,6 +207,8 @@
 	/* Device-Model */
 	struct device		astribank;
 #define	dev_to_xbus(dev)	container_of(dev, struct xbus, astribank)
+	struct kref		kref;
+#define kref_to_xbus(k) container_of(k, struct xbus, kref)
 
 	spinlock_t		lock;
 
@@ -326,6 +329,8 @@
 
 int	xpp_driver_init(void);
 void	xpp_driver_exit(void);
+int	xbus_sysfs_transport_create(xbus_t *xbus);
+void	xbus_sysfs_transport_remove(xbus_t *xbus);
 int	xbus_sysfs_create(xbus_t *xbus);
 void	xbus_sysfs_remove(xbus_t *xbus);
 

Modified: linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c?view=diff&rev=8900&r1=8899&r2=8900
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c (original)
+++ linux/trunk/drivers/dahdi/xpp/xbus-sysfs.c Tue Jul 13 10:10:30 2010
@@ -781,8 +781,6 @@
 		XPD_ERR(xpd, "%s: device_register failed: %d\n", __FUNCTION__, ret);
 		return ret;
 	}
-	xpd = get_xpd(__func__, xpd);	/* Released in xbus_release_xpds() */
-	BUG_ON(!xpd);
 	return 0;
 }
 
@@ -804,7 +802,7 @@
 
 /*--------- Sysfs Device handling ----*/
 
-void xbus_sysfs_remove(xbus_t *xbus)
+void xbus_sysfs_transport_remove(xbus_t *xbus)
 {
 	struct device	*astribank;
 
@@ -812,6 +810,33 @@
 	XBUS_DBG(DEVICES, xbus, "\n");
 	astribank = &xbus->astribank;
 	sysfs_remove_link(&astribank->kobj, "transport");
+}
+
+int xbus_sysfs_transport_create(xbus_t *xbus)
+{
+	struct device	*astribank;
+	int		ret = 0;
+
+	BUG_ON(!xbus);
+	XBUS_DBG(DEVICES, xbus, "\n");
+	astribank = &xbus->astribank;
+	ret = sysfs_create_link(&astribank->kobj, &astribank->parent->kobj,
+			"transport");
+	if (ret < 0) {
+		XBUS_ERR(xbus, "%s: sysfs_create_link failed: %d\n",
+				__func__, ret);
+		dev_set_drvdata(astribank, NULL);
+	}
+	return ret;
+}
+
+void xbus_sysfs_remove(xbus_t *xbus)
+{
+	struct device	*astribank;
+
+	BUG_ON(!xbus);
+	XBUS_DBG(DEVICES, xbus, "\n");
+	astribank = &xbus->astribank;
 	if(!dev_get_drvdata(astribank))
 		return;
 	BUG_ON(dev_get_drvdata(astribank) != xbus);
@@ -836,15 +861,7 @@
 	if(ret) {
 		XBUS_ERR(xbus, "%s: device_register failed: %d\n", __FUNCTION__, ret);
 		dev_set_drvdata(astribank, NULL);
-		goto out;
-	}
-	ret = sysfs_create_link(&astribank->kobj, &astribank->parent->kobj, "transport");
-	if(ret < 0) {
-		XBUS_ERR(xbus, "%s: sysfs_create_link failed: %d\n", __FUNCTION__, ret);
-		dev_set_drvdata(astribank, NULL);
-		goto out;
-	}
-out:
+	}
 	return ret;
 }
 

Modified: linux/trunk/drivers/dahdi/xpp/xpd.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xpd.h?view=diff&rev=8900&r1=8899&r2=8900
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xpd.h (original)
+++ linux/trunk/drivers/dahdi/xpp/xpd.h Tue Jul 13 10:10:30 2010
@@ -177,6 +177,8 @@
 	enum xpd_state	xpd_state;
 	struct device	xpd_dev;
 #define	dev_to_xpd(dev)	container_of(dev, struct xpd, xpd_dev)
+	struct kref		kref;
+#define kref_to_xpd(k) container_of(k, struct xpd, kref)
 
 	/* Assure atomicity of changes to pcm_len and wanted_pcm_mask */
 	spinlock_t	lock_recompute_pcm;

Modified: linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c?view=diff&rev=8900&r1=8899&r2=8900
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c (original)
+++ linux/trunk/drivers/dahdi/xpp/xpp_dahdi.c Tue Jul 13 10:10:30 2010
@@ -122,30 +122,38 @@
 
 /*------------------------- XPD Management -------------------------*/
 
+/*
+ * Called by put_xpd() when XPD has no more references.
+ */
+static void xpd_destroy(struct kref *kref)
+{
+	xpd_t	*xpd;
+
+	xpd = kref_to_xpd(kref);
+	XPD_NOTICE(xpd, "%s\n", __func__);
+	xpd_device_unregister(xpd);
+}
+
 int refcount_xpd(xpd_t *xpd)
 {
-	struct kref *kref = &xpd->xpd_dev.kobj.kref;
+	struct kref *kref = &xpd->kref;
 
 	return atomic_read(&kref->refcount);
 }
 
 xpd_t *get_xpd(const char *msg, xpd_t *xpd)
 {
-	struct device	*dev;
-
 	XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n",
 		msg, refcount_xpd(xpd));
-	dev = get_device(&xpd->xpd_dev);
-	if (!dev)
-		return NULL;
-	return dev_to_xpd(dev);
+	kref_get(&xpd->kref);
+	return xpd;
 }
 
 void put_xpd(const char *msg, xpd_t *xpd)
 {
 	XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n",
 		msg, refcount_xpd(xpd));
-	put_device(&xpd->xpd_dev);
+	kref_put(&xpd->kref, xpd_destroy);
 }
 
 static void xpd_proc_remove(xbus_t *xbus, xpd_t *xpd)
@@ -539,6 +547,7 @@
 
 	atomic_set(&xpd->dahdi_registered, 0);
 	atomic_set(&xpd->open_counter, 0);
+	kref_init(&xpd->kref);
 
 	/* For USB-1 disable some channels */
 	if(MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) {
@@ -614,7 +623,6 @@
 					dahdi_qevent_lock(XPD_CHAN(xpd, j),DAHDI_EVENT_REMOVED);
 				}
 			}
-			xpd_device_unregister(xpd);
 		}
 	}
 }




More information about the svn-commits mailing list