usb_gigaset: code cleanup
[deliverable/linux.git] / drivers / isdn / gigaset / common.c
index e4141bf8b2f3a705436115491bab35a18e198062..690ac74c82a8b3d6dbe06949aa61ee57b73a335a 100644 (file)
 #define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers"
 #define DRIVER_DESC "Driver for Gigaset 307x"
 
+#ifdef CONFIG_GIGASET_DEBUG
+#define DRIVER_DESC_DEBUG " (debug build)"
+#else
+#define DRIVER_DESC_DEBUG ""
+#endif
+
 /* Module parameters */
 int gigaset_debuglevel = DEBUG_DEFAULT;
 EXPORT_SYMBOL_GPL(gigaset_debuglevel);
@@ -32,6 +38,17 @@ MODULE_PARM_DESC(debug, "debug level");
 #define VALID_MINOR    0x01
 #define VALID_ID       0x02
 
+/**
+ * gigaset_dbg_buffer() - dump data in ASCII and hex for debugging
+ * @level:     debugging level.
+ * @msg:       message prefix.
+ * @len:       number of bytes to dump.
+ * @buf:       data to dump.
+ *
+ * If the current debugging level includes one of the bits set in @level,
+ * @len bytes starting at @buf are logged to dmesg at KERN_DEBUG prio,
+ * prefixed by the text @msg.
+ */
 void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
                        size_t len, const unsigned char *buf)
 {
@@ -190,6 +207,32 @@ int gigaset_get_channel(struct bc_state *bcs)
        return 1;
 }
 
+struct bc_state *gigaset_get_free_channel(struct cardstate *cs)
+{
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&cs->lock, flags);
+       if (!try_module_get(cs->driver->owner)) {
+               gig_dbg(DEBUG_ANY,
+                       "could not get module for allocating channel");
+               spin_unlock_irqrestore(&cs->lock, flags);
+               return NULL;
+       }
+       for (i = 0; i < cs->channels; ++i)
+               if (!cs->bcs[i].use_count) {
+                       ++cs->bcs[i].use_count;
+                       cs->bcs[i].busy = 1;
+                       spin_unlock_irqrestore(&cs->lock, flags);
+                       gig_dbg(DEBUG_ANY, "allocated channel %d", i);
+                       return cs->bcs + i;
+               }
+       module_put(cs->driver->owner);
+       spin_unlock_irqrestore(&cs->lock, flags);
+       gig_dbg(DEBUG_ANY, "no free channel");
+       return NULL;
+}
+
 void gigaset_free_channel(struct bc_state *bcs)
 {
        unsigned long flags;
@@ -274,6 +317,20 @@ static void clear_events(struct cardstate *cs)
        spin_unlock_irqrestore(&cs->ev_lock, flags);
 }
 
+/**
+ * gigaset_add_event() - add event to device event queue
+ * @cs:                device descriptor structure.
+ * @at_state:  connection state structure.
+ * @type:      event type.
+ * @ptr:       pointer parameter for event.
+ * @parameter: integer parameter for event.
+ * @arg:       pointer parameter for event.
+ *
+ * Allocate an event queue entry from the device's event queue, and set it up
+ * with the parameters given.
+ *
+ * Return value: added event
+ */
 struct event_t *gigaset_add_event(struct cardstate *cs,
                                  struct at_state_t *at_state, int type,
                                  void *ptr, int parameter, void *arg)
@@ -343,9 +400,9 @@ static void gigaset_freebcs(struct bc_state *bcs)
        gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
        clear_at_state(&bcs->at_state);
        gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
+       dev_kfree_skb(bcs->skb);
+       bcs->skb = NULL;
 
-       if (bcs->skb)
-               dev_kfree_skb(bcs->skb);
        for (i = 0; i < AT_NUM; ++i) {
                kfree(bcs->commands[i]);
                bcs->commands[i] = NULL;
@@ -398,6 +455,15 @@ static void make_invalid(struct cardstate *cs, unsigned mask)
        spin_unlock_irqrestore(&drv->lock, flags);
 }
 
+/**
+ * gigaset_freecs() - free all associated ressources of a device
+ * @cs:                device descriptor structure.
+ *
+ * Stops all tasklets and timers, unregisters the device from all
+ * subsystems it was registered to, deallocates the device structure
+ * @cs and all structures referenced from it.
+ * Operations on the device should be stopped before calling this.
+ */
 void gigaset_freecs(struct cardstate *cs)
 {
        int i;
@@ -423,6 +489,12 @@ void gigaset_freecs(struct cardstate *cs)
 
        switch (cs->cs_init) {
        default:
+               /* clear B channel structures */
+               for (i = 0; i < cs->channels; ++i) {
+                       gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
+                       gigaset_freebcs(cs->bcs + i);
+               }
+
                /* clear device sysfs */
                gigaset_free_dev_sysfs(cs);
 
@@ -437,22 +509,16 @@ void gigaset_freecs(struct cardstate *cs)
        case 2: /* error in initcshw */
                /* Deregister from LL */
                make_invalid(cs, VALID_ID);
-               gig_dbg(DEBUG_INIT, "clearing iif");
-               gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
+               gigaset_isdn_unregister(cs);
 
                /* fall through */
-       case 1: /* error when regestering to LL */
+       case 1: /* error when registering to LL */
                gig_dbg(DEBUG_INIT, "clearing at_state");
                clear_at_state(&cs->at_state);
                dealloc_at_states(cs);
 
                /* fall through */
-       case 0: /* error in one call to initbcs */
-               for (i = 0; i < cs->channels; ++i) {
-                       gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
-                       gigaset_freebcs(cs->bcs + i);
-               }
-
+       case 0: /* error in basic setup */
                clear_events(cs);
                gig_dbg(DEBUG_INIT, "freeing inbuf");
                kfree(cs->inbuf);
@@ -494,19 +560,21 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
 }
 
 
-static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
-                              struct cardstate *cs, int inputstate)
+static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs)
 /* inbuf->read must be allocated before! */
 {
        inbuf->head = 0;
        inbuf->tail = 0;
        inbuf->cs = cs;
-       inbuf->bcs = bcs; /*base driver: NULL*/
-       inbuf->rcvbuf = NULL;
-       inbuf->inputstate = inputstate;
+       inbuf->inputstate = INS_command;
 }
 
-/* append received bytes to inbuf */
+/**
+ * gigaset_fill_inbuf() - append received data to input buffer
+ * @inbuf:     buffer structure.
+ * @src:       received data.
+ * @numbytes:  number of bytes received.
+ */
 int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
                       unsigned numbytes)
 {
@@ -573,13 +641,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
        bcs->fcs = PPP_INITFCS;
        bcs->inputstate = 0;
        if (cs->ignoreframes) {
-               bcs->inputstate |= INS_skip_frame;
                bcs->skb = NULL;
-       } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
-               skb_reserve(bcs->skb, HW_HDR_LEN);
-       else {
-               pr_err("out of memory\n");
-               bcs->inputstate |= INS_skip_frame;
+       } else {
+               bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
+               if (bcs->skb != NULL)
+                       skb_reserve(bcs->skb, cs->hw_hdr_len);
+               else
+                       pr_err("out of memory\n");
        }
 
        bcs->channel = channel;
@@ -600,26 +668,28 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
        gig_dbg(DEBUG_INIT, "  failed");
 
        gig_dbg(DEBUG_INIT, "  freeing bcs[%d]->skb", channel);
-       if (bcs->skb)
-               dev_kfree_skb(bcs->skb);
+       dev_kfree_skb(bcs->skb);
+       bcs->skb = NULL;
 
        return NULL;
 }
 
-/* gigaset_initcs
+/**
+ * gigaset_initcs() - initialize device structure
+ * @drv:       hardware driver the device belongs to
+ * @channels:  number of B channels supported by device
+ * @onechannel:        !=0 if B channel data and AT commands share one
+ *                 communication channel (M10x),
+ *             ==0 if B channels have separate communication channels (base)
+ * @ignoreframes:      number of frames to ignore after setting up B channel
+ * @cidmode:   !=0: start in CallID mode
+ * @modulename:        name of driver module for LL registration
+ *
  * Allocate and initialize cardstate structure for Gigaset driver
  * Calls hardware dependent gigaset_initcshw() function
  * Calls B channel initialization function gigaset_initbcs() for each B channel
- * parameters:
- *     drv             hardware driver the device belongs to
- *     channels        number of B channels supported by device
- *     onechannel      !=0: B channel data and AT commands share one
- *                          communication channel
- *                     ==0: B channels have separate communication channels
- *     ignoreframes    number of frames to ignore after setting up B channel
- *     cidmode         !=0: start in CallID mode
- *     modulename      name of driver module (used for I4L registration)
- * return value:
+ *
+ * Return value:
  *     pointer to cardstate structure
  */
 struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
@@ -679,14 +749,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
        cs->mode = M_UNKNOWN;
        cs->mstate = MS_UNINITIALIZED;
 
-       for (i = 0; i < channels; ++i) {
-               gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
-               if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
-                       pr_err("could not allocate channel %d data\n", i);
-                       goto error;
-               }
-       }
-
        ++cs->cs_init;
 
        gig_dbg(DEBUG_INIT, "setting up at_state");
@@ -696,10 +758,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
        cs->cbytes = 0;
 
        gig_dbg(DEBUG_INIT, "setting up inbuf");
-       if (onechannel) {                       //FIXME distinction necessary?
-               gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command);
-       } else
-               gigaset_inbuf_init(cs->inbuf, NULL,    cs, INS_command);
+       gigaset_inbuf_init(cs->inbuf, cs);
 
        cs->connected = 0;
        cs->isdn_up = 0;
@@ -711,7 +770,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
        cs->cmdbytes = 0;
 
        gig_dbg(DEBUG_INIT, "setting up iif");
-       if (!gigaset_register_to_LL(cs, modulename)) {
+       if (!gigaset_isdn_register(cs, modulename)) {
                pr_err("error registering ISDN device\n");
                goto error;
        }
@@ -730,6 +789,15 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
        /* set up device sysfs */
        gigaset_init_dev_sysfs(cs);
 
+       /* set up channel data structures */
+       for (i = 0; i < channels; ++i) {
+               gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i);
+               if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
+                       pr_err("could not allocate channel %d data\n", i);
+                       goto error;
+               }
+       }
+
        spin_lock_irqsave(&cs->lock, flags);
        cs->running = 1;
        spin_unlock_irqrestore(&cs->lock, flags);
@@ -777,9 +845,10 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
        bcs->chstate = 0;
 
        bcs->ignore = cs->ignoreframes;
-       if (bcs->ignore)
-               bcs->inputstate |= INS_skip_frame;
-
+       if (bcs->ignore) {
+               dev_kfree_skb(bcs->skb);
+               bcs->skb = NULL;
+       }
 
        cs->ops->reinitbcshw(bcs);
 }
@@ -800,8 +869,6 @@ static void cleanup_cs(struct cardstate *cs)
        free_strings(&cs->at_state);
        gigaset_at_init(&cs->at_state, NULL, cs, 0);
 
-       kfree(cs->inbuf->rcvbuf);
-       cs->inbuf->rcvbuf = NULL;
        cs->inbuf->inputstate = INS_command;
        cs->inbuf->head = 0;
        cs->inbuf->tail = 0;
@@ -837,6 +904,17 @@ static void cleanup_cs(struct cardstate *cs)
 }
 
 
+/**
+ * gigaset_start() - start device operations
+ * @cs:                device descriptor structure.
+ *
+ * Prepares the device for use by setting up communication parameters,
+ * scheduling an EV_START event to initiate device initialization, and
+ * waiting for completion of the initialization.
+ *
+ * Return value:
+ *     1 - success, 0 - error
+ */
 int gigaset_start(struct cardstate *cs)
 {
        unsigned long flags;
@@ -879,9 +957,15 @@ error:
 }
 EXPORT_SYMBOL_GPL(gigaset_start);
 
-/* gigaset_shutdown
- * check if a device is associated to the cardstate structure and stop it
- * return value: 0 if ok, -1 if no device was associated
+/**
+ * gigaset_shutdown() - shut down device operations
+ * @cs:                device descriptor structure.
+ *
+ * Deactivates the device by scheduling an EV_SHUTDOWN event and
+ * waiting for completion of the shutdown.
+ *
+ * Return value:
+ *     0 - success, -1 - error (no device associated)
  */
 int gigaset_shutdown(struct cardstate *cs)
 {
@@ -912,6 +996,13 @@ exit:
 }
 EXPORT_SYMBOL_GPL(gigaset_shutdown);
 
+/**
+ * gigaset_stop() - stop device operations
+ * @cs:                device descriptor structure.
+ *
+ * Stops operations on the device by scheduling an EV_STOP event and
+ * waiting for completion of the shutdown.
+ */
 void gigaset_stop(struct cardstate *cs)
 {
        mutex_lock(&cs->mutex);
@@ -1020,6 +1111,14 @@ struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
        return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
 }
 
+/**
+ * gigaset_freedriver() - free all associated ressources of a driver
+ * @drv:       driver descriptor structure.
+ *
+ * Unregisters the driver from the system and deallocates the driver
+ * structure @drv and all structures referenced from it.
+ * All devices should be shut down before calling this.
+ */
 void gigaset_freedriver(struct gigaset_driver *drv)
 {
        unsigned long flags;
@@ -1035,14 +1134,16 @@ void gigaset_freedriver(struct gigaset_driver *drv)
 }
 EXPORT_SYMBOL_GPL(gigaset_freedriver);
 
-/* gigaset_initdriver
+/**
+ * gigaset_initdriver() - initialize driver structure
+ * @minor:     First minor number
+ * @minors:    Number of minors this driver can handle
+ * @procname:  Name of the driver
+ * @devname:   Name of the device files (prefix without minor number)
+ *
  * Allocate and initialize gigaset_driver structure. Initialize interface.
- * parameters:
- *     minor           First minor number
- *     minors          Number of minors this driver can handle
- *     procname        Name of the driver
- *     devname         Name of the device files (prefix without minor number)
- * return value:
+ *
+ * Return value:
  *     Pointer to the gigaset_driver structure on success, NULL on failure.
  */
 struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
@@ -1095,6 +1196,13 @@ error:
 }
 EXPORT_SYMBOL_GPL(gigaset_initdriver);
 
+/**
+ * gigaset_blockdriver() - block driver
+ * @drv:       driver descriptor structure.
+ *
+ * Prevents the driver from attaching new devices, in preparation for
+ * deregistration.
+ */
 void gigaset_blockdriver(struct gigaset_driver *drv)
 {
        drv->blocked = 1;
@@ -1110,7 +1218,7 @@ static int __init gigaset_init_module(void)
        if (gigaset_debuglevel == 1)
                gigaset_debuglevel = DEBUG_DEFAULT;
 
-       pr_info(DRIVER_DESC "\n");
+       pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n");
        return 0;
 }
 
This page took 0.029122 seconds and 5 git commands to generate.