Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[powerpc.git] / drivers / isdn / gigaset / common.c
index c3c9804..acb7e26 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Stuff used by all variants of the driver
  *
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
  *                       Hansjoerg Lipp <hjlipp@web.de>,
  *                       Tilman Schmidt <tilman@imap.cc>.
  *
@@ -19,7 +19,7 @@
 #include <linux/moduleparam.h>
 
 /* Version Information */
-#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers"
 #define DRIVER_DESC "Driver for Gigaset 307x"
 
 /* Module parameters */
@@ -28,15 +28,7 @@ EXPORT_SYMBOL_GPL(gigaset_debuglevel);
 module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(debug, "debug level");
 
-/*======================================================================
-  Prototypes of internal functions
- */
-
-static struct cardstate *alloc_cs(struct gigaset_driver *drv);
-static void free_cs(struct cardstate *cs);
-static void make_valid(struct cardstate *cs, unsigned mask);
-static void make_invalid(struct cardstate *cs, unsigned mask);
-
+/* driver state flags */
 #define VALID_MINOR    0x01
 #define VALID_ID       0x02
 #define ASSIGNED       0x04
@@ -137,11 +129,6 @@ int gigaset_enterconfigmode(struct cardstate *cs)
 {
        int i, r;
 
-       if (!atomic_read(&cs->connected)) {
-               err("not connected!");
-               return -1;
-       }
-
        cs->control_state = TIOCM_RTS; //FIXME
 
        r = setflags(cs, TIOCM_DTR, 200);
@@ -184,7 +171,7 @@ static int test_timeout(struct at_state_t *at_state)
        }
 
        if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL,
-                              atomic_read(&at_state->timer_index), NULL)) {
+                              at_state->timer_index, NULL)) {
                //FIXME what should we do?
        }
 
@@ -212,7 +199,7 @@ static void timer_tick(unsigned long data)
                if (test_timeout(at_state))
                        timeout = 1;
 
-       if (atomic_read(&cs->running)) {
+       if (cs->running) {
                mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK));
                if (timeout) {
                        gig_dbg(DEBUG_CMD, "scheduling timeout");
@@ -306,20 +293,22 @@ static void clear_events(struct cardstate *cs)
 {
        struct event_t *ev;
        unsigned head, tail;
+       unsigned long flags;
 
-       /* no locking needed (no reader/writer allowed) */
+       spin_lock_irqsave(&cs->ev_lock, flags);
 
-       head = atomic_read(&cs->ev_head);
-       tail = atomic_read(&cs->ev_tail);
+       head = cs->ev_head;
+       tail = cs->ev_tail;
 
        while (tail != head) {
                ev = cs->events + head;
                kfree(ev->ptr);
-
                head = (head + 1) % MAX_EVENTS;
        }
 
-       atomic_set(&cs->ev_head, tail);
+       cs->ev_head = tail;
+
+       spin_unlock_irqrestore(&cs->ev_lock, flags);
 }
 
 struct event_t *gigaset_add_event(struct cardstate *cs,
@@ -332,9 +321,9 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
 
        spin_lock_irqsave(&cs->ev_lock, flags);
 
-       tail = atomic_read(&cs->ev_tail);
+       tail = cs->ev_tail;
        next = (tail + 1) % MAX_EVENTS;
-       if (unlikely(next == atomic_read(&cs->ev_head)))
+       if (unlikely(next == cs->ev_head))
                err("event queue full");
        else {
                event = cs->events + tail;
@@ -344,7 +333,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
                event->ptr = ptr;
                event->arg = arg;
                event->parameter = parameter;
-               atomic_set(&cs->ev_tail, next);
+               cs->ev_tail = next;
        }
 
        spin_unlock_irqrestore(&cs->ev_lock, flags);
@@ -400,6 +389,52 @@ static void gigaset_freebcs(struct bc_state *bcs)
        }
 }
 
+static struct cardstate *alloc_cs(struct gigaset_driver *drv)
+{
+       unsigned long flags;
+       unsigned i;
+       static 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)
+                       break;
+       }
+       spin_unlock_irqrestore(&drv->lock, flags);
+       return ret;
+}
+
+static void free_cs(struct cardstate *cs)
+{
+       unsigned long flags;
+       struct gigaset_driver *drv = cs->driver;
+       spin_lock_irqsave(&drv->lock, flags);
+       drv->flags[cs->minor_index] = 0;
+       spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_valid(struct cardstate *cs, unsigned mask)
+{
+       unsigned long flags;
+       struct gigaset_driver *drv = cs->driver;
+       spin_lock_irqsave(&drv->lock, flags);
+       drv->flags[cs->minor_index] |= mask;
+       spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_invalid(struct cardstate *cs, unsigned mask)
+{
+       unsigned long flags;
+       struct gigaset_driver *drv = cs->driver;
+       spin_lock_irqsave(&drv->lock, flags);
+       drv->flags[cs->minor_index] &= ~mask;
+       spin_unlock_irqrestore(&drv->lock, flags);
+}
+
 void gigaset_freecs(struct cardstate *cs)
 {
        int i;
@@ -416,7 +451,7 @@ void gigaset_freecs(struct cardstate *cs)
                goto f_bcs;
 
        spin_lock_irqsave(&cs->lock, flags);
-       atomic_set(&cs->running, 0);
+       cs->running = 0;
        spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are
                                                     not rescheduled below */
 
@@ -425,6 +460,9 @@ void gigaset_freecs(struct cardstate *cs)
 
        switch (cs->cs_init) {
        default:
+               /* clear device sysfs */
+               gigaset_free_dev_sysfs(cs);
+
                gigaset_if_free(cs);
 
                gig_dbg(DEBUG_INIT, "clearing hw");
@@ -475,8 +513,8 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
        at_state->pending_commands = 0;
        at_state->timer_expires = 0;
        at_state->timer_active = 0;
-       atomic_set(&at_state->timer_index, 0);
-       atomic_set(&at_state->seq_index, 0);
+       at_state->timer_index = 0;
+       at_state->seq_index = 0;
        at_state->ConState = 0;
        for (i = 0; i < STR_NUM; ++i)
                at_state->str_var[i] = NULL;
@@ -627,6 +665,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
                                 int cidmode, const char *modulename)
 {
        struct cardstate *cs = NULL;
+       unsigned long flags;
        int i;
 
        gig_dbg(DEBUG_INIT, "allocating cs");
@@ -647,11 +686,11 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
        cs->onechannel = onechannel;
        cs->ignoreframes = ignoreframes;
        INIT_LIST_HEAD(&cs->temp_at_states);
-       atomic_set(&cs->running, 0);
+       cs->running = 0;
        init_timer(&cs->timer); /* clear next & prev */
        spin_lock_init(&cs->ev_lock);
-       atomic_set(&cs->ev_tail, 0);
-       atomic_set(&cs->ev_head, 0);
+       cs->ev_tail = 0;
+       cs->ev_head = 0;
        mutex_init(&cs->mutex);
        mutex_lock(&cs->mutex);
 
@@ -663,7 +702,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
        cs->open_count = 0;
        cs->dev = NULL;
        cs->tty = NULL;
-       atomic_set(&cs->cidmode, cidmode != 0);
+       cs->class = NULL;
+       cs->cidmode = cidmode != 0;
 
        //if(onechannel) { //FIXME
                cs->tabnocid = gigaset_tab_nocid_m10x;
@@ -699,7 +739,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
        } else
                gigaset_inbuf_init(cs->inbuf, NULL,    cs, INS_command);
 
-       atomic_set(&cs->connected, 0);
+       cs->connected = 0;
+       cs->isdn_up = 0;
 
        gig_dbg(DEBUG_INIT, "setting up cmdbuf");
        cs->cmdbuf = cs->lastcmdbuf = NULL;
@@ -723,7 +764,12 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
 
        gigaset_if_init(cs);
 
-       atomic_set(&cs->running, 1);
+       /* set up device sysfs */
+       gigaset_init_dev_sysfs(cs);
+
+       spin_lock_irqsave(&cs->lock, flags);
+       cs->running = 1;
+       spin_unlock_irqrestore(&cs->lock, flags);
        setup_timer(&cs->timer, timer_tick, (unsigned long) cs);
        cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK);
        /* FIXME: can jiffies increase too much until the timer is added?
@@ -742,8 +788,7 @@ error:      if (cs)
 }
 EXPORT_SYMBOL_GPL(gigaset_initcs);
 
-/* ReInitialize the b-channel structure */
-/* e.g. called on hangup, disconnect */
+/* ReInitialize the b-channel structure on hangup */
 void gigaset_bcs_reinit(struct bc_state *bcs)
 {
        struct sk_buff *skb;
@@ -833,10 +878,14 @@ static void cleanup_cs(struct cardstate *cs)
 
 int gigaset_start(struct cardstate *cs)
 {
+       unsigned long flags;
+
        if (mutex_lock_interruptible(&cs->mutex))
                return 0;
 
-       atomic_set(&cs->connected, 1);
+       spin_lock_irqsave(&cs->lock, flags);
+       cs->connected = 1;
+       spin_unlock_irqrestore(&cs->lock, flags);
 
        if (atomic_read(&cs->mstate) != MS_LOCKED) {
                cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
@@ -860,9 +909,6 @@ int gigaset_start(struct cardstate *cs)
 
        wait_event(cs->waitqueue, !cs->waiting);
 
-       /* set up device sysfs */
-       gigaset_init_dev_sysfs(cs);
-
        mutex_unlock(&cs->mutex);
        return 1;
 
@@ -912,11 +958,6 @@ void gigaset_stop(struct cardstate *cs)
 {
        mutex_lock(&cs->mutex);
 
-       /* clear device sysfs */
-       gigaset_free_dev_sysfs(cs);
-
-       atomic_set(&cs->connected, 0);
-
        cs->waiting = 1;
 
        if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) {
@@ -932,9 +973,6 @@ void gigaset_stop(struct cardstate *cs)
                //FIXME
        }
 
-       /* Tell the LL that the device is not available .. */
-       gigaset_i4l_cmd(cs, ISDN_STAT_STOP); // FIXME move to event layer?
-
        cleanup_cs(cs);
 
 exit:
@@ -999,16 +1037,8 @@ void gigaset_debugdrivers(void)
        }
        spin_unlock_irqrestore(&driver_lock, flags);
 }
-EXPORT_SYMBOL_GPL(gigaset_debugdrivers);
 
-struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
-{
-       if (tty->index < 0 || tty->index >= tty->driver->num)
-               return NULL;
-       return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
-}
-
-struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
+static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
 {
        unsigned long flags;
        static struct cardstate *ret = NULL;
@@ -1031,6 +1061,13 @@ struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
        return ret;
 }
 
+struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
+{
+       if (tty->index < 0 || tty->index >= tty->driver->num)
+               return NULL;
+       return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
+}
+
 void gigaset_freedriver(struct gigaset_driver *drv)
 {
        unsigned long flags;
@@ -1073,8 +1110,9 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
        drv = kmalloc(sizeof *drv, GFP_KERNEL);
        if (!drv)
                return NULL;
+
        if (!try_module_get(owner))
-               return NULL;
+               goto out1;
 
        drv->cs = NULL;
        drv->have_tty = 0;
@@ -1088,10 +1126,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
 
        drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
        if (!drv->cs)
-               goto out1;
+               goto out2;
+
        drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
        if (!drv->flags)
-               goto out2;
+               goto out3;
 
        for (i = 0; i < minors; ++i) {
                drv->flags[i] = 0;
@@ -1108,61 +1147,16 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
 
        return drv;
 
-out2:
+out3:
        kfree(drv->cs);
+out2:
+       module_put(owner);
 out1:
        kfree(drv);
-       module_put(owner);
        return NULL;
 }
 EXPORT_SYMBOL_GPL(gigaset_initdriver);
 
-static struct cardstate *alloc_cs(struct gigaset_driver *drv)
-{
-       unsigned long flags;
-       unsigned i;
-       static 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)
-                       break;
-       }
-       spin_unlock_irqrestore(&drv->lock, flags);
-       return ret;
-}
-
-static void free_cs(struct cardstate *cs)
-{
-       unsigned long flags;
-       struct gigaset_driver *drv = cs->driver;
-       spin_lock_irqsave(&drv->lock, flags);
-       drv->flags[cs->minor_index] = 0;
-       spin_unlock_irqrestore(&drv->lock, flags);
-}
-
-static void make_valid(struct cardstate *cs, unsigned mask)
-{
-       unsigned long flags;
-       struct gigaset_driver *drv = cs->driver;
-       spin_lock_irqsave(&drv->lock, flags);
-       drv->flags[cs->minor_index] |= mask;
-       spin_unlock_irqrestore(&drv->lock, flags);
-}
-
-static void make_invalid(struct cardstate *cs, unsigned mask)
-{
-       unsigned long flags;
-       struct gigaset_driver *drv = cs->driver;
-       spin_lock_irqsave(&drv->lock, flags);
-       drv->flags[cs->minor_index] &= ~mask;
-       spin_unlock_irqrestore(&drv->lock, flags);
-}
-
 /* For drivers without fixed assignment device<->cardstate (usb) */
 struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv)
 {