(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:
Frank A. Uepping 2004-08-29 18:06:26 +00:00
parent e420314971
commit 1d19193852
1 changed files with 12 additions and 48 deletions

View File

@ -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;