summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/isdn/gigaset/common.c61
1 files changed, 33 insertions, 28 deletions
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 95eff3b2917a..4f75cce6fdff 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -356,16 +356,17 @@ static struct cardstate *alloc_cs(struct gigaset_driver *drv)
{
unsigned long flags;
unsigned i;
- static struct cardstate *ret = NULL;
+ struct cardstate *ret = NULL;
spin_lock_irqsave(&drv->lock, flags);
for (i = 0; i < drv->minors; ++i) {
if (!(drv->flags[i] & VALID_MINOR)) {
- drv->flags[i] = VALID_MINOR;
- ret = drv->cs + i;
- }
- if (ret)
+ if (try_module_get(drv->owner)) {
+ drv->flags[i] = VALID_MINOR;
+ ret = drv->cs + i;
+ }
break;
+ }
}
spin_unlock_irqrestore(&drv->lock, flags);
return ret;
@@ -376,6 +377,8 @@ static void free_cs(struct cardstate *cs)
unsigned long flags;
struct gigaset_driver *drv = cs->driver;
spin_lock_irqsave(&drv->lock, flags);
+ if (drv->flags[cs->minor_index] & VALID_MINOR)
+ module_put(drv->owner);
drv->flags[cs->minor_index] = 0;
spin_unlock_irqrestore(&drv->lock, flags);
}
@@ -579,7 +582,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else {
- warn("could not allocate skb\n");
+ warn("could not allocate skb");
bcs->inputstate |= INS_skip_frame;
}
@@ -632,17 +635,25 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
int i;
gig_dbg(DEBUG_INIT, "allocating cs");
- cs = alloc_cs(drv);
- if (!cs)
- goto error;
+ if (!(cs = alloc_cs(drv))) {
+ err("maximum number of devices exceeded");
+ return NULL;
+ }
+ mutex_init(&cs->mutex);
+ mutex_lock(&cs->mutex);
+
gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
- if (!cs->bcs)
+ if (!cs->bcs) {
+ err("out of memory");
goto error;
+ }
gig_dbg(DEBUG_INIT, "allocating inbuf");
cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
- if (!cs->inbuf)
+ if (!cs->inbuf) {
+ err("out of memory");
goto error;
+ }
cs->cs_init = 0;
cs->channels = channels;
@@ -654,8 +665,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
spin_lock_init(&cs->ev_lock);
cs->ev_tail = 0;
cs->ev_head = 0;
- mutex_init(&cs->mutex);
- mutex_lock(&cs->mutex);
tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
(unsigned long) cs);
@@ -684,8 +693,10 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
for (i = 0; i < channels; ++i) {
gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
- if (!gigaset_initbcs(cs->bcs + i, cs, i))
+ if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
+ err("could not allocate channel %d data", i);
goto error;
+ }
}
++cs->cs_init;
@@ -720,8 +731,10 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
make_valid(cs, VALID_ID);
++cs->cs_init;
gig_dbg(DEBUG_INIT, "setting up hw");
- if (!cs->ops->initcshw(cs))
+ if (!cs->ops->initcshw(cs)) {
+ err("could not allocate device specific data");
goto error;
+ }
++cs->cs_init;
@@ -743,8 +756,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
mutex_unlock(&cs->mutex);
return cs;
-error: if (cs)
- mutex_unlock(&cs->mutex);
+error:
+ mutex_unlock(&cs->mutex);
gig_dbg(DEBUG_INIT, "failed");
gigaset_freecs(cs);
return NULL;
@@ -1040,7 +1053,6 @@ void gigaset_freedriver(struct gigaset_driver *drv)
spin_unlock_irqrestore(&driver_lock, flags);
gigaset_if_freedriver(drv);
- module_put(drv->owner);
kfree(drv->cs);
kfree(drv->flags);
@@ -1072,10 +1084,6 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
if (!drv)
return NULL;
- if (!try_module_get(owner))
- goto out1;
-
- drv->cs = NULL;
drv->have_tty = 0;
drv->minor = minor;
drv->minors = minors;
@@ -1087,11 +1095,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
if (!drv->cs)
- goto out2;
+ goto error;
drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
if (!drv->flags)
- goto out3;
+ goto error;
for (i = 0; i < minors; ++i) {
drv->flags[i] = 0;
@@ -1108,11 +1116,8 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
return drv;
-out3:
+error:
kfree(drv->cs);
-out2:
- module_put(owner);
-out1:
kfree(drv);
return NULL;
}