]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/isdn/gigaset/common.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6
[linux-2.6-omap-h63xx.git] / drivers / isdn / gigaset / common.c
index 95eff3b2917ae868b8717f153eb94a1022991673..acd417197d03dd6f46078bff2eff31fb05bf5414 100644 (file)
@@ -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);
 }
@@ -531,7 +534,8 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
                        n = RBUFSIZE - tail;
                if (!n) {
                        dev_err(inbuf->cs->dev,
-                               "buffer overflow (%u bytes lost)", bytesleft);
+                               "buffer overflow (%u bytes lost)\n",
+                               bytesleft);
                        break;
                }
                if (n > bytesleft)
@@ -579,7 +583,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 +636,24 @@ 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);
+
        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,11 +731,14 @@ 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;
 
+       /* set up character device */
        gigaset_if_init(cs);
 
        /* set up device sysfs */
@@ -740,11 +754,9 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
        add_timer(&cs->timer);
 
        gig_dbg(DEBUG_INIT, "cs initialized");
-       mutex_unlock(&cs->mutex);
        return cs;
 
-error: if (cs)
-               mutex_unlock(&cs->mutex);
+error:
        gig_dbg(DEBUG_INIT, "failed");
        gigaset_freecs(cs);
        return NULL;
@@ -895,20 +907,7 @@ void gigaset_shutdown(struct cardstate *cs)
        gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN");
        gigaset_schedule_event(cs);
 
-       if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
-               warn("%s: aborted", __func__);
-               //FIXME
-       }
-
-       if (atomic_read(&cs->mstate) != MS_LOCKED) {
-               //FIXME?
-               //gigaset_baud_rate(cs, B115200);
-               //gigaset_set_line_ctrl(cs, CS8);
-               //gigaset_set_modem_ctrl(cs, TIOCM_DTR|TIOCM_RTS, 0);
-               //cs->control_state = 0;
-       } else {
-               //FIXME use some saved values?
-       }
+       wait_event(cs->waitqueue, !cs->waiting);
 
        cleanup_cs(cs);
 
@@ -931,10 +930,7 @@ void gigaset_stop(struct cardstate *cs)
        gig_dbg(DEBUG_CMD, "scheduling STOP");
        gigaset_schedule_event(cs);
 
-       if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
-               warn("%s: aborted", __func__);
-               //FIXME
-       }
+       wait_event(cs->waitqueue, !cs->waiting);
 
        cleanup_cs(cs);
 
@@ -949,8 +945,8 @@ static DEFINE_SPINLOCK(driver_lock);
 struct cardstate *gigaset_get_cs_by_id(int id)
 {
        unsigned long flags;
-       static struct cardstate *ret = NULL;
-       static struct cardstate *cs;
+       struct cardstate *ret = NULL;
+       struct cardstate *cs;
        struct gigaset_driver *drv;
        unsigned i;
 
@@ -1004,7 +1000,7 @@ void gigaset_debugdrivers(void)
 static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
 {
        unsigned long flags;
-       static struct cardstate *ret = NULL;
+       struct cardstate *ret = NULL;
        struct gigaset_driver *drv;
        unsigned index;
 
@@ -1040,7 +1036,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 +1067,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 +1078,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 +1099,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;
 }