Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[powerpc.git] / drivers / isdn / gigaset / usb-gigaset.c
index 323fc73..6e05d9d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * USB driver for Gigaset 307x directly or using M105 Data.
  *
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>
+ * Copyright (c) 2001 by Stefan Eilers
  *                   and Hansjoerg Lipp <hjlipp@web.de>.
  *
  * This driver was derived from the USB skeleton driver by
  *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
  * =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: usb-gigaset.c,v 1.85.4.18 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
@@ -29,7 +25,7 @@
 #include <linux/moduleparam.h>
 
 /* Version Information */
-#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers"
 #define DRIVER_DESC "USB Driver for Gigaset 307x using M105"
 
 /* Module parameters */
@@ -45,7 +41,6 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
 #define GIGASET_MINORS     1
 #define GIGASET_MINOR      8
 #define GIGASET_MODULENAME "usb_gigaset"
-#define GIGASET_DEVFSNAME  "gig/usb/"
 #define GIGASET_DEVNAME    "ttyGU"
 
 #define IF_WRITEBUF 2000 //FIXME  // WAKEUP_CHARS: 256
@@ -62,10 +57,6 @@ static struct usb_device_id gigaset_table [] = {
 
 MODULE_DEVICE_TABLE(usb, gigaset_table);
 
-/* Get a minor range for your devices from the usb maintainer */
-#define USB_SKEL_MINOR_BASE    200
-
-
 /*
  * Control requests (empty fields: 00)
  *
@@ -114,7 +105,7 @@ MODULE_DEVICE_TABLE(usb, gigaset_table);
  */
 
 static int gigaset_probe(struct usb_interface *interface,
-                         const struct usb_device_id *id);
+                        const struct usb_device_id *id);
 static void gigaset_disconnect(struct usb_interface *interface);
 
 static struct gigaset_driver *driver = NULL;
@@ -122,29 +113,29 @@ static struct cardstate *cardstate = NULL;
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver gigaset_usb_driver = {
-       .name =         GIGASET_MODULENAME,
-       .probe =        gigaset_probe,
-       .disconnect =   gigaset_disconnect,
-       .id_table =     gigaset_table,
+       .name =         GIGASET_MODULENAME,
+       .probe =        gigaset_probe,
+       .disconnect =   gigaset_disconnect,
+       .id_table =     gigaset_table,
 };
 
 struct usb_cardstate {
-       struct usb_device       *udev;                  /* save off the usb device pointer */
-       struct usb_interface    *interface;             /* the interface for this device */
-       atomic_t                busy;                   /* bulk output in progress */
-
-       /* Output buffer for commands (M105: and data)*/
-       unsigned char           *bulk_out_buffer;       /* the buffer to send data */
-       int                     bulk_out_size;          /* the size of the send buffer */
-       __u8                    bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
-       struct urb              *bulk_out_urb;          /* the urb used to transmit data */
-
-       /* Input buffer for command responses (M105: and data)*/
-       int                     rcvbuf_size;            /* the size of the receive buffer */
-       struct urb              *read_urb;              /* the urb used to receive data */
-       __u8                    int_in_endpointAddr;    /* the address of the bulk in endpoint */
-
-       char                    bchars[6];              /* req. 0x19 */
+       struct usb_device       *udev;          /* usb device pointer */
+       struct usb_interface    *interface;     /* interface for this device */
+       atomic_t                busy;           /* bulk output in progress */
+
+       /* Output buffer */
+       unsigned char           *bulk_out_buffer;
+       int                     bulk_out_size;
+       __u8                    bulk_out_endpointAddr;
+       struct urb              *bulk_out_urb;
+
+       /* Input buffer */
+       int                     rcvbuf_size;
+       struct urb              *read_urb;
+       __u8                    int_in_endpointAddr;
+
+       char                    bchars[6];              /* for request 0x19 */
 };
 
 struct usb_bc_state {};
@@ -157,19 +148,20 @@ static inline unsigned tiocm_to_gigaset(unsigned state)
 #ifdef CONFIG_GIGASET_UNDOCREQ
 /* WARNING: EXPERIMENTAL! */
 static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
-                                  unsigned new_state)
+                                 unsigned new_state)
 {
+       struct usb_device *udev = cs->hw.usb->udev;
        unsigned mask, val;
        int r;
 
        mask = tiocm_to_gigaset(old_state ^ new_state);
        val = tiocm_to_gigaset(new_state);
 
-       dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
-       r = usb_control_msg(cs->hw.usb->udev,
-                           usb_sndctrlpipe(cs->hw.usb->udev, 0), 7, 0x41,
-                           (val & 0xff) | ((mask & 0xff) << 8), 0,
-                           NULL, 0, 2000 /*timeout??*/); // don't use this in an interrupt/BH
+       gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
+       // don't use this in an interrupt/BH
+       r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41,
+                           (val & 0xff) | ((mask & 0xff) << 8), 0,
+                           NULL, 0, 2000 /* timeout? */);
        if (r < 0)
                return r;
        //..
@@ -178,30 +170,29 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
 
 static int set_value(struct cardstate *cs, u8 req, u16 val)
 {
+       struct usb_device *udev = cs->hw.usb->udev;
        int r, r2;
 
-       dbg(DEBUG_USBREQ, "request %02x (%04x)", (unsigned)req, (unsigned)val);
-       r = usb_control_msg(cs->hw.usb->udev,
-                           usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x12, 0x41,
-                           0xf /*?*/, 0,
-                           NULL, 0, 2000 /*?*/); /* no idea, what this does */
+       gig_dbg(DEBUG_USBREQ, "request %02x (%04x)",
+               (unsigned)req, (unsigned)val);
+       r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41,
+                           0xf /*?*/, 0, NULL, 0, 2000 /*?*/);
+                           /* no idea what this does */
        if (r < 0) {
-               err("error %d on request 0x12", -r);
+               dev_err(&udev->dev, "error %d on request 0x12\n", -r);
                return r;
        }
 
-       r = usb_control_msg(cs->hw.usb->udev,
-                           usb_sndctrlpipe(cs->hw.usb->udev, 0), req, 0x41,
-                           val, 0,
-                           NULL, 0, 2000 /*?*/);
+       r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, 0x41,
+                           val, 0, NULL, 0, 2000 /*?*/);
        if (r < 0)
-               err("error %d on request 0x%02x", -r, (unsigned)req);
+               dev_err(&udev->dev, "error %d on request 0x%02x\n",
+                       -r, (unsigned)req);
 
-       r2 = usb_control_msg(cs->hw.usb->udev,
-                            usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
-                            0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
+       r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
+                            0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
        if (r2 < 0)
-               err("error %d on request 0x19", -r2);
+               dev_err(&udev->dev, "error %d on request 0x19\n", -r2);
 
        return r < 0 ? r : (r2 < 0 ? r2 : 0);
 }
@@ -229,8 +220,8 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
        case B115200: rate =  115200; break;
        default:
                rate =  9600;
-               err("unsupported baudrate request 0x%x,"
-                   " using default of B9600", cflag);
+               dev_err(cs->dev, "unsupported baudrate request 0x%x,"
+                       " using default of B9600\n", cflag);
        }
 
        val = 0x383fff / rate + 1;
@@ -259,7 +250,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
        case CS8:
                val |= 8 << 8; break;
        default:
-               err("CSIZE was not CS5-CS8, using default of 8");
+               dev_err(cs->dev, "CSIZE was not CS5-CS8, using default of 8\n");
                val |= 8 << 8;
                break;
        }
@@ -277,7 +268,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
 
 #else
 static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
-                                  unsigned new_state)
+                                 unsigned new_state)
 {
        return -EINVAL;
 }
@@ -309,15 +300,12 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
        return 0;
 }
 
-//void send_ack_to_LL(void *data);
 static int write_modem(struct cardstate *cs);
 static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb);
 
 
-/* Handling of send queue. If there is already a skb opened, put data to
- * the transfer buffer by calling "write_modem". Otherwise take a new skb out of the queue.
- * This function will be called by the ISR via "transmit_chars" (USB: B-Channel Bulk callback handler
- * via immediate task queue) or by writebuf_from_LL if the LL wants to transmit data.
+/* Write tasklet handler: Continue sending current skb, or send command, or
+ * start sending an skb from the send queue.
  */
 static void gigaset_modem_fill(unsigned long data)
 {
@@ -327,10 +315,10 @@ static void gigaset_modem_fill(unsigned long data)
        unsigned long flags;
        int again;
 
-       dbg(DEBUG_OUTPUT, "modem_fill");
+       gig_dbg(DEBUG_OUTPUT, "modem_fill");
 
        if (atomic_read(&cs->hw.usb->busy)) {
-               dbg(DEBUG_OUTPUT, "modem_fill: busy");
+               gig_dbg(DEBUG_OUTPUT, "modem_fill: busy");
                return;
        }
 
@@ -341,26 +329,27 @@ static void gigaset_modem_fill(unsigned long data)
                        cb = cs->cmdbuf;
                        spin_unlock_irqrestore(&cs->cmdlock, flags);
                        if (cb) { /* commands to send? */
-                               dbg(DEBUG_OUTPUT, "modem_fill: cb");
+                               gig_dbg(DEBUG_OUTPUT, "modem_fill: cb");
                                if (send_cb(cs, cb) < 0) {
-                                       dbg(DEBUG_OUTPUT,
-                                           "modem_fill: send_cb failed");
-                                       again = 1; /* no callback will be called! */
+                                       gig_dbg(DEBUG_OUTPUT,
+                                               "modem_fill: send_cb failed");
+                                       again = 1; /* no callback will be
+                                                     called! */
                                }
                        } else { /* skbs to send? */
                                bcs->tx_skb = skb_dequeue(&bcs->squeue);
                                if (bcs->tx_skb)
-                                       dbg(DEBUG_INTR,
-                                           "Dequeued skb (Adr: %lx)!",
-                                           (unsigned long) bcs->tx_skb);
+                                       gig_dbg(DEBUG_INTR,
+                                               "Dequeued skb (Adr: %lx)!",
+                                               (unsigned long) bcs->tx_skb);
                        }
                }
 
                if (bcs->tx_skb) {
-                       dbg(DEBUG_OUTPUT, "modem_fill: tx_skb");
+                       gig_dbg(DEBUG_OUTPUT, "modem_fill: tx_skb");
                        if (write_modem(cs) < 0) {
-                               dbg(DEBUG_OUTPUT,
-                                   "modem_fill: write_modem failed");
+                               gig_dbg(DEBUG_OUTPUT,
+                                       "modem_fill: write_modem failed");
                                // FIXME should we tell the LL?
                                again = 1; /* no callback will be called! */
                        }
@@ -371,88 +360,85 @@ static void gigaset_modem_fill(unsigned long data)
 /**
  *     gigaset_read_int_callback
  *
- *      It is called if the data was received from the device. This is almost similiar to
- *      the interrupt service routine in the serial device.
+ *     It is called if the data was received from the device.
  */
 static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
 {
+       struct inbuf_t *inbuf = urb->context;
+       struct cardstate *cs = inbuf->cs;
        int resubmit = 0;
        int r;
-       struct cardstate *cs;
        unsigned numbytes;
        unsigned char *src;
-       //unsigned long flags;
-       struct inbuf_t *inbuf;
-
-       IFNULLRET(urb);
-       inbuf = (struct inbuf_t *) urb->context;
-       IFNULLRET(inbuf);
-       //spin_lock_irqsave(&inbuf->lock, flags);
-       cs = inbuf->cs;
-       IFNULLGOTO(cs, exit);
-       IFNULLGOTO(cardstate, exit);
-
-       if (!atomic_read(&cs->connected)) {
-               err("%s: disconnected", __func__);
-               goto exit;
-       }
+       unsigned long flags;
 
        if (!urb->status) {
+               if (!cs->connected) {
+                       err("%s: disconnected", __func__); /* should never happen */
+                       return;
+               }
+
                numbytes = urb->actual_length;
 
                if (numbytes) {
                        src = inbuf->rcvbuf;
                        if (unlikely(*src))
-                               warn("%s: There was no leading 0, but 0x%02x!",
-                                    __func__, (unsigned) *src);
+                               dev_warn(cs->dev,
+                                   "%s: There was no leading 0, but 0x%02x!\n",
+                                        __func__, (unsigned) *src);
                        ++src; /* skip leading 0x00 */
                        --numbytes;
                        if (gigaset_fill_inbuf(inbuf, src, numbytes)) {
-                               dbg(DEBUG_INTR, "%s-->BH", __func__);
+                               gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
                                gigaset_schedule_event(inbuf->cs);
                        }
                } else
-                       dbg(DEBUG_INTR, "Received zero block length");
+                       gig_dbg(DEBUG_INTR, "Received zero block length");
                resubmit = 1;
        } else {
                /* The urb might have been killed. */
-               dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
-                   __func__, urb->status);
-               if (urb->status != -ENOENT) /* not killed */
+               gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
+                       __func__, urb->status);
+               if (urb->status != -ENOENT) { /* not killed */
+                       if (!cs->connected) {
+                               err("%s: disconnected", __func__); /* should never happen */
+                               return;
+                       }
                        resubmit = 1;
+               }
        }
-exit:
-       //spin_unlock_irqrestore(&inbuf->lock, flags);
+
        if (resubmit) {
-               r = usb_submit_urb(urb, SLAB_ATOMIC);
+               spin_lock_irqsave(&cs->lock, flags);
+               r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
+               spin_unlock_irqrestore(&cs->lock, flags);
                if (r)
-                       err("error %d when resubmitting urb.", -r);
+                       dev_err(cs->dev, "error %d when resubmitting urb.\n",
+                               -r);
        }
 }
 
 
-/* This callback routine is called when data was transmitted to a B-Channel.
- * Therefore it has to check if there is still data to transmit. This
- * happens by calling modem_fill via task queue.
- *
- */
+/* This callback routine is called when data was transmitted to the device. */
 static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
-       struct cardstate *cs = (struct cardstate *) urb->context;
+       struct cardstate *cs = urb->context;
+       unsigned long flags;
 
-       IFNULLRET(cs);
-#ifdef CONFIG_GIGASET_DEBUG
-       if (!atomic_read(&cs->connected)) {
-               err("%s:not connected", __func__);
-               return;
-       }
-#endif
        if (urb->status)
-               err("bulk transfer failed (status %d)", -urb->status); /* That's all we can do. Communication problems
-                                                                          are handeled by timeouts or network protocols */
+               dev_err(cs->dev, "bulk transfer failed (status %d)\n",
+                       -urb->status);
+               /* That's all we can do. Communication problems
+                  are handled by timeouts or network protocols. */
 
-       atomic_set(&cs->hw.usb->busy, 0);
-       tasklet_schedule(&cs->write_tasklet);
+       spin_lock_irqsave(&cs->lock, flags);
+       if (!cs->connected) {
+               err("%s: not connected", __func__);
+       } else {
+               atomic_set(&cs->hw.usb->busy, 0);
+               tasklet_schedule(&cs->write_tasklet);
+       }
+       spin_unlock_irqrestore(&cs->lock, flags);
 }
 
 static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
@@ -469,8 +455,8 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
 
                        spin_lock_irqsave(&cs->cmdlock, flags);
                        cs->cmdbytes -= cs->curlen;
-                       dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left",
-                           cs->curlen, cs->cmdbytes);
+                       gig_dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left",
+                               cs->curlen, cs->cmdbytes);
                        cs->cmdbuf = cb = cb->next;
                        if (cb) {
                                cb->prev = NULL;
@@ -487,52 +473,51 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
                }
                if (cb) {
                        count = min(cb->len, ucs->bulk_out_size);
+                       gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
+
                        usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
-                                         usb_sndbulkpipe(ucs->udev,
-                                            ucs->bulk_out_endpointAddr & 0x0f),
-                                         cb->buf + cb->offset, count,
-                                         gigaset_write_bulk_callback, cs);
+                                         usb_sndbulkpipe(ucs->udev,
+                                            ucs->bulk_out_endpointAddr & 0x0f),
+                                         cb->buf + cb->offset, count,
+                                         gigaset_write_bulk_callback, cs);
 
                        cb->offset += count;
                        cb->len -= count;
                        atomic_set(&ucs->busy, 1);
-                       dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
 
-                       status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+                       spin_lock_irqsave(&cs->lock, flags);
+                       status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV;
+                       spin_unlock_irqrestore(&cs->lock, flags);
+
                        if (status) {
                                atomic_set(&ucs->busy, 0);
-                               err("could not submit urb (error %d).",
+                               err("could not submit urb (error %d)\n",
                                    -status);
-                               cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */
+                               cb->len = 0; /* skip urb => remove cb+wakeup
+                                               in next loop cycle */
                        }
                }
-       } while (cb && status); /* bei Fehler naechster Befehl //FIXME: ist das OK? */
+       } while (cb && status); /* next command on error */
 
        return status;
 }
 
-/* Write string into transbuf and send it to modem.
- */
+/* Send command to device. */
 static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
-                             int len, struct tasklet_struct *wake_tasklet)
+                            int len, struct tasklet_struct *wake_tasklet)
 {
        struct cmdbuf_t *cb;
        unsigned long flags;
 
        gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
-                            DEBUG_TRANSCMD : DEBUG_LOCKCMD,
-                          "CMD Transmit", len, buf, 0);
-
-       if (!atomic_read(&cs->connected)) {
-               err("%s: not connected", __func__);
-               return -ENODEV;
-       }
+                            DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+                          "CMD Transmit", len, buf);
 
        if (len <= 0)
                return 0;
 
        if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
-               err("%s: out of memory", __func__);
+               dev_err(cs->dev, "%s: out of memory\n", __func__);
                return -ENOMEM;
        }
 
@@ -554,7 +539,10 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
        cs->lastcmdbuf = cb;
        spin_unlock_irqrestore(&cs->cmdlock, flags);
 
-       tasklet_schedule(&cs->write_tasklet);
+       spin_lock_irqsave(&cs->lock, flags);
+       if (cs->connected)
+               tasklet_schedule(&cs->write_tasklet);
+       spin_unlock_irqrestore(&cs->lock, flags);
        return len;
 }
 
@@ -578,11 +566,12 @@ static int gigaset_chars_in_buffer(struct cardstate *cs)
 static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
 {
 #ifdef CONFIG_GIGASET_UNDOCREQ
-       gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf, 0);
+       struct usb_device *udev = cs->hw.usb->udev;
+
+       gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf);
        memcpy(cs->hw.usb->bchars, buf, 6);
-       return usb_control_msg(cs->hw.usb->udev,
-                              usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
-                              0, 0, &buf, 6, 2000);
+       return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
+                              0, 0, &buf, 6, 2000);
 #else
        return -EINVAL;
 #endif
@@ -604,7 +593,6 @@ static int gigaset_initbcshw(struct bc_state *bcs)
        if (!bcs->hw.usb)
                return 0;
 
-       //bcs->hw.usb->trans_flg = READY_TO_TRNSMIT; /* B-Channel ready to transmit */
        return 1;
 }
 
@@ -614,7 +602,6 @@ static void gigaset_reinitbcshw(struct bc_state *bcs)
 
 static void gigaset_freecshw(struct cardstate *cs)
 {
-       //FIXME
        tasklet_kill(&cs->write_tasklet);
        kfree(cs->hw.usb);
 }
@@ -639,33 +626,21 @@ static int gigaset_initcshw(struct cardstate *cs)
        //ucs->urb_cmd_out = NULL;
        ucs->read_urb = NULL;
        tasklet_init(&cs->write_tasklet,
-                    &gigaset_modem_fill, (unsigned long) cs);
+                    &gigaset_modem_fill, (unsigned long) cs);
 
        return 1;
 }
 
-/* Writes the data of the current open skb into the modem.
- * We have to protect against multiple calls until the
- * callback handler () is called , due to the fact that we
- * are just allowed to send data once to an endpoint. Therefore
- * we using "trans_flg" to synchonize ...
- */
+/* Send data from current skb to the device. */
 static int write_modem(struct cardstate *cs)
 {
-       int ret;
+       int ret = 0;
        int count;
        struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
        struct usb_cardstate *ucs = cs->hw.usb;
-       //unsigned long flags;
-
-       IFNULLRETVAL(bcs->tx_skb, -EINVAL);
-
-       dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
+       unsigned long flags;
 
-       ret = -ENODEV;
-       IFNULLGOTO(ucs->bulk_out_buffer, error);
-       IFNULLGOTO(ucs->bulk_out_urb, error);
-       ret = 0;
+       gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
 
        if (!bcs->tx_skb->len) {
                dev_kfree_skb_any(bcs->tx_skb);
@@ -679,40 +654,42 @@ static int write_modem(struct cardstate *cs)
        count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
        memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count);
        skb_pull(bcs->tx_skb, count);
-
-       usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
-                         usb_sndbulkpipe(ucs->udev,
-                                         ucs->bulk_out_endpointAddr & 0x0f),
-                         ucs->bulk_out_buffer, count,
-                         gigaset_write_bulk_callback, cs);
        atomic_set(&ucs->busy, 1);
-       dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
+       gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
+
+       spin_lock_irqsave(&cs->lock, flags);
+       if (cs->connected) {
+               usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
+                                 usb_sndbulkpipe(ucs->udev,
+                                                 ucs->bulk_out_endpointAddr & 0x0f),
+                                 ucs->bulk_out_buffer, count,
+                                 gigaset_write_bulk_callback, cs);
+               ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+       } else {
+               ret = -ENODEV;
+       }
+       spin_unlock_irqrestore(&cs->lock, flags);
 
-       ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
        if (ret) {
-               err("could not submit urb (error %d).", -ret);
+               err("could not submit urb (error %d)\n", -ret);
                atomic_set(&ucs->busy, 0);
        }
+
        if (!bcs->tx_skb->len) {
                /* skb sent completely */
                gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0?
 
-               dbg(DEBUG_INTR,
-                   "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb);
+               gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
+                       (unsigned long) bcs->tx_skb);
                dev_kfree_skb_any(bcs->tx_skb);
                bcs->tx_skb = NULL;
        }
 
        return ret;
-error:
-       dev_kfree_skb_any(bcs->tx_skb);
-       bcs->tx_skb = NULL;
-       return ret;
-
 }
 
 static int gigaset_probe(struct usb_interface *interface,
-                         const struct usb_device_id *id)
+                        const struct usb_device_id *id)
 {
        int retval;
        struct usb_device *udev = interface_to_usbdev(interface);
@@ -720,22 +697,20 @@ static int gigaset_probe(struct usb_interface *interface,
        struct usb_host_interface *hostif;
        struct cardstate *cs = NULL;
        struct usb_cardstate *ucs = NULL;
-       //struct usb_interface_descriptor *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
-       //isdn_ctrl command;
        int buffer_size;
        int alt;
-       //unsigned long flags;
 
-       info("%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
-           __func__, le16_to_cpu(udev->descriptor.idVendor),
-           le16_to_cpu(udev->descriptor.idProduct));
+       gig_dbg(DEBUG_ANY,
+               "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+               __func__, le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct));
 
        retval = -ENODEV; //FIXME
 
        /* See if the device offered us matches what we can accept */
-       if ((le16_to_cpu(udev->descriptor.idVendor  != USB_M105_VENDOR_ID)) ||
-           (le16_to_cpu(udev->descriptor.idProduct != USB_M105_PRODUCT_ID)))
+       if ((le16_to_cpu(udev->descriptor.idVendor)  != USB_M105_VENDOR_ID) ||
+           (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID))
                return -ENODEV;
 
        /* this starts to become ascii art... */
@@ -744,7 +719,7 @@ static int gigaset_probe(struct usb_interface *interface,
        ifnum = hostif->desc.bInterfaceNumber; // FIXME ?
 
        if (alt != 0 || ifnum != 0) {
-               warn("ifnum %d, alt %d", ifnum, alt);
+               dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt);
                return -ENODEV;
        }
 
@@ -752,42 +727,29 @@ static int gigaset_probe(struct usb_interface *interface,
         *
         */
        if (hostif->desc.bInterfaceClass != 255) {
-               info("%s: Device matched, but iface_desc[%d]->bInterfaceClass==%d !",
-                      __func__, ifnum, hostif->desc.bInterfaceClass);
+               dev_info(&udev->dev,
+               "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n",
+                        __func__, ifnum, hostif->desc.bInterfaceClass);
                return -ENODEV;
        }
 
-       info("%s: Device matched ... !", __func__);
+       dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
 
        cs = gigaset_getunassignedcs(driver);
        if (!cs) {
-               warn("No free cardstate!");
+               dev_warn(&udev->dev, "no free cardstate\n");
                return -ENODEV;
        }
        ucs = cs->hw.usb;
 
-#if 0
-       if (usb_set_configuration(udev, udev->config[0].desc.bConfigurationValue) < 0) {
-               warn("set_configuration failed");
-               goto error;
-       }
-
-
-       if (usb_set_interface(udev, ifnum/*==0*/, alt/*==0*/) < 0) {
-               warn("usb_set_interface failed, device %d interface %d altsetting %d",
-                    udev->devnum, ifnum, alt);
-               goto error;
-       }
-#endif
+       /* save off device structure ptrs for later use */
+       usb_get_dev(udev);
+       ucs->udev = udev;
+       ucs->interface = interface;
+       cs->dev = &interface->dev;
 
-       /* set up the endpoint information */
-       /* check out the endpoints */
-       /* We will get 2 endpoints: One for sending commands to the device (bulk out) and one to
-        * poll messages from the device(int in).
-        * Therefore we will have an almost similiar situation as with our serial port handler.
-        * If an connection will be established, we will have to create data in/out pipes
-        * dynamically...
-        */
+       /* save address of controller structure */
+       usb_set_intfdata(interface, cs); // dev_set_drvdata(&interface->dev, cs);
 
        endpoint = &hostif->endpoint[0].desc;
 
@@ -796,14 +758,14 @@ static int gigaset_probe(struct usb_interface *interface,
        ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress;
        ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
        if (!ucs->bulk_out_buffer) {
-               err("Couldn't allocate bulk_out_buffer");
+               dev_err(cs->dev, "Couldn't allocate bulk_out_buffer\n");
                retval = -ENOMEM;
                goto error;
        }
 
        ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL);
        if (!ucs->bulk_out_urb) {
-               err("Couldn't allocate bulk_out_buffer");
+               dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n");
                retval = -ENOMEM;
                goto error;
        }
@@ -811,12 +773,10 @@ static int gigaset_probe(struct usb_interface *interface,
        endpoint = &hostif->endpoint[1].desc;
 
        atomic_set(&ucs->busy, 0);
-       ucs->udev = udev;
-       ucs->interface = interface;
 
        ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL);
        if (!ucs->read_urb) {
-               err("No free urbs available");
+               dev_err(cs->dev, "No free urbs available\n");
                retval = -ENOMEM;
                goto error;
        }
@@ -825,38 +785,33 @@ static int gigaset_probe(struct usb_interface *interface,
        ucs->int_in_endpointAddr = endpoint->bEndpointAddress;
        cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
        if (!cs->inbuf[0].rcvbuf) {
-               err("Couldn't allocate rcvbuf");
+               dev_err(cs->dev, "Couldn't allocate rcvbuf\n");
                retval = -ENOMEM;
                goto error;
        }
        /* Fill the interrupt urb and send it to the core */
        usb_fill_int_urb(ucs->read_urb, udev,
-                        usb_rcvintpipe(udev,
-                                       endpoint->bEndpointAddress & 0x0f),
-                        cs->inbuf[0].rcvbuf, buffer_size,
-                        gigaset_read_int_callback,
-                        cs->inbuf + 0, endpoint->bInterval);
+                        usb_rcvintpipe(udev,
+                                       endpoint->bEndpointAddress & 0x0f),
+                        cs->inbuf[0].rcvbuf, buffer_size,
+                        gigaset_read_int_callback,
+                        cs->inbuf + 0, endpoint->bInterval);
 
        retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL);
        if (retval) {
-               err("Could not submit URB!");
+               dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval);
                goto error;
        }
 
        /* tell common part that the device is ready */
        if (startmode == SM_LOCKED)
                atomic_set(&cs->mstate, MS_LOCKED);
+
        if (!gigaset_start(cs)) {
                tasklet_kill(&cs->write_tasklet);
                retval = -ENODEV; //FIXME
                goto error;
        }
-
-       /* save address of controller structure */
-       usb_set_intfdata(interface, cs);
-
-       /* set up device sysfs */
-       gigaset_init_dev_sysfs(interface);
        return 0;
 
 error:
@@ -868,48 +823,45 @@ error:
        kfree(cs->inbuf[0].rcvbuf);
        if (ucs->read_urb != NULL)
                usb_free_urb(ucs->read_urb);
+       usb_set_intfdata(interface, NULL);
        ucs->read_urb = ucs->bulk_out_urb = NULL;
        cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+       usb_put_dev(ucs->udev);
+       ucs->udev = NULL;
+       ucs->interface = NULL;
        gigaset_unassign(cs);
        return retval;
 }
 
-/**
- *     skel_disconnect
- */
 static void gigaset_disconnect(struct usb_interface *interface)
 {
        struct cardstate *cs;
        struct usb_cardstate *ucs;
 
        cs = usb_get_intfdata(interface);
-
-       /* clear device sysfs */
-       gigaset_free_dev_sysfs(interface);
-
-       usb_set_intfdata(interface, NULL);
        ucs = cs->hw.usb;
        usb_kill_urb(ucs->read_urb);
-       //info("GigaSet USB device #%d will be disconnected", minor);
 
        gigaset_stop(cs);
 
+       usb_set_intfdata(interface, NULL);
        tasklet_kill(&cs->write_tasklet);
 
-       usb_kill_urb(ucs->bulk_out_urb);  /* FIXME: nur, wenn noetig */
-       //usb_kill_urb(ucs->urb_cmd_out);  /* FIXME: nur, wenn noetig */
+       usb_kill_urb(ucs->bulk_out_urb);        /* FIXME: only if active? */
 
        kfree(ucs->bulk_out_buffer);
        if (ucs->bulk_out_urb != NULL)
                usb_free_urb(ucs->bulk_out_urb);
-       //if(ucs->urb_cmd_out != NULL)
-       //      usb_free_urb(ucs->urb_cmd_out);
        kfree(cs->inbuf[0].rcvbuf);
        if (ucs->read_urb != NULL)
                usb_free_urb(ucs->read_urb);
-       ucs->read_urb = ucs->bulk_out_urb/*=ucs->urb_cmd_out*/=NULL;
+       ucs->read_urb = ucs->bulk_out_urb = NULL;
        cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
 
+       usb_put_dev(ucs->udev);
+       ucs->interface = NULL;
+       ucs->udev = NULL;
+       cs->dev = NULL;
        gigaset_unassign(cs);
 }
 
@@ -942,9 +894,8 @@ static int __init usb_gigaset_init(void)
 
        /* allocate memory for our driver state and intialize it */
        if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
-                                      GIGASET_MODULENAME, GIGASET_DEVNAME,
-                                      GIGASET_DEVFSNAME, &ops,
-                                      THIS_MODULE)) == NULL)
+                                      GIGASET_MODULENAME, GIGASET_DEVNAME,
+                                      &ops, THIS_MODULE)) == NULL)
                goto error;
 
        /* allocate memory for our device state and intialize it */
@@ -981,8 +932,8 @@ error:      if (cardstate)
 static void __exit usb_gigaset_exit(void)
 {
        gigaset_blockdriver(driver); /* => probe will fail
-                                     * => no gigaset_start any more
-                                     */
+                                     * => no gigaset_start any more
+                                     */
 
        gigaset_shutdown(cardstate);
        /* from now on, no isdn callback should be possible */