diff options
author | Tzafrir Cohen <tzafrir.cohen@xorcom.com> | 2010-07-13 15:10:30 +0000 |
---|---|---|
committer | Tzafrir Cohen <tzafrir.cohen@xorcom.com> | 2010-07-13 15:10:30 +0000 |
commit | fe0081acc9a07f762121338e9e3f523b240ed178 (patch) | |
tree | e8e2174cb2e859ef0e22b987a0f9544e26d44628 /drivers/dahdi/xpp/xbus-core.c | |
parent | 921654884fd0ad506e7f7f6a34760a905f96b2ea (diff) |
Keep SYSFS objects after disconnect
When the USB device disconnects, we keep references to them to make sure
they don't disappear.
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@8900 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/xpp/xbus-core.c')
-rw-r--r-- | drivers/dahdi/xpp/xbus-core.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/drivers/dahdi/xpp/xbus-core.c b/drivers/dahdi/xpp/xbus-core.c index 569b678..2d2ecb4 100644 --- a/drivers/dahdi/xpp/xbus-core.c +++ b/drivers/dahdi/xpp/xbus-core.c @@ -141,28 +141,36 @@ static void finalize_xbuses_array(void) } } -xbus_t *get_xbus(const char *msg, xbus_t *xbus) +/* + * Called by put_xbus() when XBUS has no more references. + */ +static void xbus_destroy(struct kref *kref) { - struct device *dev; + 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) +{ 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 @@ static void worker_reset(xbus_t *xbus) 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 @@ void xbus_deactivate(xbus_t *xbus) 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 @@ void xbus_disconnect(xbus_t *xbus) 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,6 +1435,7 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *tran 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; @@ -1435,6 +1444,12 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *tran 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); #ifdef CONFIG_PROC_FS XBUS_DBG(PROC, xbus, "Creating xbus proc directory\n"); |