(capi_device_register, release_capi_device, capi_register, capi_release): Module reference counting removed.
(register_capi_device): Increment of nr_capi_devices moved to capi_device_register(). (get_capi_device): Removed. (capi_peek_message): Pending info is returned. (capi_device_register): Moved call to capi_device_register_sysfs() to end. (capi_device_unregister): Moved call to class_device_del() after changing state.
This commit is contained in:
parent
e420314971
commit
1d19193852
|
@ -22,7 +22,6 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/skbuff.h>
|
|
||||||
#include <linux/isdn/capidevice.h>
|
#include <linux/isdn/capidevice.h>
|
||||||
#include <linux/isdn/capiutil.h>
|
#include <linux/isdn/capiutil.h>
|
||||||
#include <linux/isdn/capicmd.h>
|
#include <linux/isdn/capicmd.h>
|
||||||
|
@ -36,13 +35,6 @@ atomic_t nr_capi_devices = ATOMIC_INIT(0);
|
||||||
int capi_device_register_sysfs (struct capi_device* dev);
|
int capi_device_register_sysfs (struct capi_device* dev);
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
get_capi_device(struct capi_device* dev)
|
|
||||||
{
|
|
||||||
kref_get(&dev->refs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct capi_device*
|
static struct capi_device*
|
||||||
try_get_capi_device(struct capi_device* dev)
|
try_get_capi_device(struct capi_device* dev)
|
||||||
{
|
{
|
||||||
|
@ -53,7 +45,7 @@ try_get_capi_device(struct capi_device* dev)
|
||||||
if (unlikely(dev->state != CAPI_DEVICE_STATE_RUNNING))
|
if (unlikely(dev->state != CAPI_DEVICE_STATE_RUNNING))
|
||||||
dev = NULL;
|
dev = NULL;
|
||||||
else
|
else
|
||||||
get_capi_device(dev);
|
kref_get(&dev->refs);
|
||||||
spin_unlock(&dev->state_lock);
|
spin_unlock(&dev->state_lock);
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
|
@ -87,11 +79,6 @@ static void
|
||||||
release_capi_device(struct kref* kref)
|
release_capi_device(struct kref* kref)
|
||||||
{
|
{
|
||||||
struct capi_device* dev = container_of(kref, struct capi_device, refs);
|
struct capi_device* dev = container_of(kref, struct capi_device, refs);
|
||||||
struct module* owner = dev->drv->owner;
|
|
||||||
|
|
||||||
int appls = atomic_read(&dev->appls);
|
|
||||||
while (appls--)
|
|
||||||
module_put(owner);
|
|
||||||
|
|
||||||
complete(&dev->done);
|
complete(&dev->done);
|
||||||
}
|
}
|
||||||
|
@ -123,8 +110,6 @@ register_capi_device(struct capi_device* dev)
|
||||||
capi_devices_table[id] = dev;
|
capi_devices_table[id] = dev;
|
||||||
spin_unlock(&capi_devices_table_lock);
|
spin_unlock(&capi_devices_table_lock);
|
||||||
|
|
||||||
atomic_inc(&nr_capi_devices);
|
|
||||||
|
|
||||||
return dev->id = id + 1;
|
return dev->id = id + 1;
|
||||||
}
|
}
|
||||||
spin_unlock(&capi_devices_table_lock);
|
spin_unlock(&capi_devices_table_lock);
|
||||||
|
@ -136,41 +121,35 @@ register_capi_device(struct capi_device* dev)
|
||||||
int
|
int
|
||||||
capi_device_register(struct capi_device* dev)
|
capi_device_register(struct capi_device* dev)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
|
|
||||||
if (unlikely(!dev))
|
if (unlikely(!dev))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (unlikely(!register_capi_device(dev)))
|
if (unlikely(!register_capi_device(dev)))
|
||||||
return -EMFILE;
|
return -EMFILE;
|
||||||
|
|
||||||
err = capi_device_register_sysfs(dev);
|
atomic_inc(&nr_capi_devices);
|
||||||
if (unlikely(err))
|
|
||||||
return err;
|
|
||||||
|
|
||||||
kref_init(&dev->refs, release_capi_device);
|
kref_init(&dev->refs, release_capi_device);
|
||||||
init_completion(&dev->done);
|
init_completion(&dev->done);
|
||||||
atomic_set(&dev->appls, 0);
|
|
||||||
spin_lock_init(&dev->stats.lock);
|
spin_lock_init(&dev->stats.lock);
|
||||||
spin_lock_init(&dev->state_lock);
|
spin_lock_init(&dev->state_lock);
|
||||||
dev->state = CAPI_DEVICE_STATE_RUNNING;
|
dev->state = CAPI_DEVICE_STATE_RUNNING;
|
||||||
|
|
||||||
return 0;
|
return capi_device_register_sysfs(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
capi_device_unregister(struct capi_device* dev)
|
capi_device_unregister(struct capi_device* dev)
|
||||||
{
|
{
|
||||||
class_device_del(&dev->class_dev);
|
|
||||||
|
|
||||||
spin_lock(&dev->state_lock);
|
spin_lock(&dev->state_lock);
|
||||||
dev->state = CAPI_DEVICE_STATE_ZOMBIE;
|
dev->state = CAPI_DEVICE_STATE_ZOMBIE;
|
||||||
spin_unlock(&dev->state_lock);
|
spin_unlock(&dev->state_lock);
|
||||||
|
|
||||||
atomic_dec(&nr_capi_devices);
|
atomic_dec(&nr_capi_devices);
|
||||||
|
|
||||||
BUG_ON(!module_is_live(dev->drv->owner) && atomic_read(&dev->refs.refcount) != 1);
|
class_device_del(&dev->class_dev);
|
||||||
|
|
||||||
put_capi_device(dev);
|
put_capi_device(dev);
|
||||||
wait_for_completion(&dev->done);
|
wait_for_completion(&dev->done);
|
||||||
}
|
}
|
||||||
|
@ -231,31 +210,18 @@ capi_register(struct capi_appl* appl)
|
||||||
|
|
||||||
spin_lock(&capi_devices_table_lock);
|
spin_lock(&capi_devices_table_lock);
|
||||||
for (id = 0; id < CAPI_MAX_DEVS; id++) {
|
for (id = 0; id < CAPI_MAX_DEVS; id++) {
|
||||||
dev = capi_devices_table[id];
|
dev = try_get_capi_device(capi_devices_table[id]);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
spin_lock(&dev->state_lock);
|
|
||||||
if (unlikely(!(dev->state == CAPI_DEVICE_STATE_RUNNING && try_module_get(dev->drv->owner)))) {
|
|
||||||
spin_unlock(&dev->state_lock);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
get_capi_device(dev);
|
|
||||||
spin_unlock(&dev->state_lock);
|
|
||||||
spin_unlock(&capi_devices_table_lock);
|
spin_unlock(&capi_devices_table_lock);
|
||||||
|
|
||||||
info = dev->drv->capi_register(dev, appl);
|
info = dev->drv->capi_register(dev, appl);
|
||||||
if (unlikely(info)) {
|
if (unlikely(info)) {
|
||||||
struct module* owner = dev->drv->owner;
|
|
||||||
|
|
||||||
printk(KERN_NOTICE "capi: CAPI_REGISTER failed on device %d (info: %#x)\n", id + 1, info);
|
printk(KERN_NOTICE "capi: CAPI_REGISTER failed on device %d (info: %#x)\n", id + 1, info);
|
||||||
|
|
||||||
put_capi_device(dev);
|
put_capi_device(dev);
|
||||||
module_put(owner);
|
|
||||||
} else {
|
} else {
|
||||||
__set_bit(id, appl->devs);
|
__set_bit(id, appl->devs);
|
||||||
atomic_inc(&dev->appls);
|
|
||||||
smp_mb__after_atomic_inc();
|
|
||||||
capi_device_get(dev);
|
capi_device_get(dev);
|
||||||
put_capi_device(dev);
|
put_capi_device(dev);
|
||||||
}
|
}
|
||||||
|
@ -279,11 +245,6 @@ capi_release(struct capi_appl* appl)
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
if (likely(try_get_capi_device(dev))) {
|
if (likely(try_get_capi_device(dev))) {
|
||||||
dev->drv->capi_release(dev, appl);
|
dev->drv->capi_release(dev, appl);
|
||||||
|
|
||||||
atomic_dec(&dev->appls);
|
|
||||||
smp_mb__after_atomic_dec();
|
|
||||||
module_put(dev->drv->owner);
|
|
||||||
|
|
||||||
put_capi_device(dev);
|
put_capi_device(dev);
|
||||||
}
|
}
|
||||||
capi_device_put(dev);
|
capi_device_put(dev);
|
||||||
|
@ -306,7 +267,7 @@ capi_put_message(struct capi_appl* appl, struct sk_buff* msg)
|
||||||
if (unlikely(info))
|
if (unlikely(info))
|
||||||
return info;
|
return info;
|
||||||
|
|
||||||
if (!msg || msg->len < CAPIMSG_BASELEN + 4)
|
if (unlikely(!msg || msg->len < CAPIMSG_BASELEN + 4))
|
||||||
return CAPINFO_0X11_ILLCMDORMSGTOSMALL;
|
return CAPINFO_0X11_ILLCMDORMSGTOSMALL;
|
||||||
|
|
||||||
id = CAPIMSG_CONTROLLER(msg->data);
|
id = CAPIMSG_CONTROLLER(msg->data);
|
||||||
|
@ -331,7 +292,7 @@ capi_get_message(struct capi_appl* appl, struct sk_buff** msg)
|
||||||
return appl->info;
|
return appl->info;
|
||||||
|
|
||||||
*msg = skb_dequeue(&appl->msg_queue);
|
*msg = skb_dequeue(&appl->msg_queue);
|
||||||
if (unlikely(!*msg))
|
if (!*msg)
|
||||||
return CAPINFO_0X11_QUEUEEMPTY;
|
return CAPINFO_0X11_QUEUEEMPTY;
|
||||||
|
|
||||||
return CAPINFO_0X11_NOERR;
|
return CAPINFO_0X11_NOERR;
|
||||||
|
@ -341,7 +302,10 @@ capi_get_message(struct capi_appl* appl, struct sk_buff** msg)
|
||||||
capinfo_0x11
|
capinfo_0x11
|
||||||
capi_peek_message(struct capi_appl* appl)
|
capi_peek_message(struct capi_appl* appl)
|
||||||
{
|
{
|
||||||
if (appl->info || !skb_queue_empty(&appl->msg_queue))
|
if (unlikely(appl->info))
|
||||||
|
return appl->info;
|
||||||
|
|
||||||
|
if (!skb_queue_empty(&appl->msg_queue))
|
||||||
return CAPINFO_0X11_QUEUEFULL;
|
return CAPINFO_0X11_QUEUEFULL;
|
||||||
|
|
||||||
return CAPINFO_0X11_QUEUEEMPTY;
|
return CAPINFO_0X11_QUEUEEMPTY;
|
||||||
|
|
Loading…
Reference in New Issue