Merge branch 'for_paulus' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc
[pandora-kernel.git] / drivers / isdn / gigaset / bas-gigaset.c
index 580831d..f86ed6a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2001 by Hansjoerg Lipp <hjlipp@web.de>,
  *                       Tilman Schmidt <tilman@imap.cc>,
- *                       Stefan Eilers <Eilers.Stefan@epost.de>.
+ *                       Stefan Eilers.
  *
  * Based on usb-gigaset.c.
  *
@@ -26,7 +26,7 @@
 #include <linux/moduleparam.h>
 
 /* Version Information */
-#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers"
 #define DRIVER_DESC "USB Driver for Gigaset 307x"
 
 
@@ -205,7 +205,6 @@ static inline void dump_urb(enum debuglevel level, const char *tag,
 {
 #ifdef CONFIG_GIGASET_DEBUG
        int i;
-       IFNULLRET(tag);
        gig_dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb);
        if (urb) {
                gig_dbg(level,
@@ -309,8 +308,6 @@ static void check_pending(struct bas_cardstate *ucs)
 {
        unsigned long flags;
 
-       IFNULLRET(ucs);
-
        spin_lock_irqsave(&ucs->lock, flags);
        switch (ucs->pending) {
        case 0:
@@ -366,15 +363,11 @@ static void check_pending(struct bas_cardstate *ucs)
 static void cmd_in_timeout(unsigned long data)
 {
        struct cardstate *cs = (struct cardstate *) data;
-       struct bas_cardstate *ucs;
+       struct bas_cardstate *ucs = cs->hw.bas;
        unsigned long flags;
 
-       IFNULLRET(cs);
-       ucs = cs->hw.bas;
-       IFNULLRET(ucs);
-
        spin_lock_irqsave(&cs->lock, flags);
-       if (unlikely(!atomic_read(&cs->connected))) {
+       if (unlikely(!cs->connected)) {
                gig_dbg(DEBUG_USBREQ, "%s: disconnected", __func__);
                spin_unlock_irqrestore(&cs->lock, flags);
                return;
@@ -406,14 +399,9 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs);
  */
 static int atread_submit(struct cardstate *cs, int timeout)
 {
-       struct bas_cardstate *ucs;
+       struct bas_cardstate *ucs = cs->hw.bas;
        int ret;
 
-       IFNULLRETVAL(cs, -EINVAL);
-       ucs = cs->hw.bas;
-       IFNULLRETVAL(ucs, -EINVAL);
-       IFNULLRETVAL(ucs->urb_cmd_in, -EINVAL);
-
        gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)",
                ucs->rcvbuf_size);
 
@@ -479,25 +467,14 @@ inline static void update_basstate(struct bas_cardstate *ucs,
  */
 static void read_int_callback(struct urb *urb, struct pt_regs *regs)
 {
-       struct cardstate *cs;
-       struct bas_cardstate *ucs;
+       struct cardstate *cs = urb->context;
+       struct bas_cardstate *ucs = cs->hw.bas;
        struct bc_state *bcs;
        unsigned long flags;
        int status;
        unsigned l;
        int channel;
 
-       IFNULLRET(urb);
-       cs = (struct cardstate *) urb->context;
-       IFNULLRET(cs);
-       ucs = cs->hw.bas;
-       IFNULLRET(ucs);
-
-       if (unlikely(!atomic_read(&cs->connected))) {
-               warn("%s: disconnected", __func__);
-               return;
-       }
-
        switch (urb->status) {
        case 0:                 /* success */
                break;
@@ -621,7 +598,9 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs)
        check_pending(ucs);
 
 resubmit:
-       status = usb_submit_urb(urb, SLAB_ATOMIC);
+       spin_lock_irqsave(&cs->lock, flags);
+       status = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
+       spin_unlock_irqrestore(&cs->lock, flags);
        if (unlikely(status)) {
                dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
                        get_usb_statmsg(status));
@@ -638,23 +617,15 @@ resubmit:
  */
 static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
 {
-       struct cardstate *cs;
-       struct bas_cardstate *ucs;
+       struct inbuf_t *inbuf = urb->context;
+       struct cardstate *cs = inbuf->cs;
+       struct bas_cardstate *ucs = cs->hw.bas;
+       int have_data = 0;
        unsigned numbytes;
        unsigned long flags;
-       struct inbuf_t *inbuf;
-       int have_data = 0;
-
-       IFNULLRET(urb);
-       inbuf = (struct inbuf_t *) urb->context;
-       IFNULLRET(inbuf);
-       cs = inbuf->cs;
-       IFNULLRET(cs);
-       ucs = cs->hw.bas;
-       IFNULLRET(ucs);
 
        spin_lock_irqsave(&cs->lock, flags);
-       if (unlikely(!atomic_read(&cs->connected))) {
+       if (unlikely(!cs->connected)) {
                warn("%s: disconnected", __func__);
                spin_unlock_irqrestore(&cs->lock, flags);
                return;
@@ -747,10 +718,6 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs)
        unsigned long flags;
        int i, rc;
 
-       IFNULLRET(urb);
-       IFNULLRET(urb->context);
-       IFNULLRET(cardstate);
-
        /* status codes not worth bothering the tasklet with */
        if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
                     urb->status == -EINPROGRESS)) {
@@ -759,9 +726,8 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs)
                return;
        }
 
-       bcs = (struct bc_state *) urb->context;
+       bcs = urb->context;
        ubc = bcs->hw.bas;
-       IFNULLRET(ubc);
 
        spin_lock_irqsave(&ubc->isoinlock, flags);
        if (likely(ubc->isoindone == NULL)) {
@@ -813,10 +779,6 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs)
        struct bas_bc_state *ubc;
        unsigned long flags;
 
-       IFNULLRET(urb);
-       IFNULLRET(urb->context);
-       IFNULLRET(cardstate);
-
        /* status codes not worth bothering the tasklet with */
        if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
                     urb->status == -EINPROGRESS)) {
@@ -826,10 +788,8 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs)
        }
 
        /* pass URB context to tasklet */
-       ucx = (struct isow_urbctx_t *) urb->context;
-       IFNULLRET(ucx->bcs);
+       ucx = urb->context;
        ubc = ucx->bcs->hw.bas;
-       IFNULLRET(ubc);
 
        spin_lock_irqsave(&ubc->isooutlock, flags);
        ubc->isooutovfl = ubc->isooutdone;
@@ -848,15 +808,11 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs)
  */
 static int starturbs(struct bc_state *bcs)
 {
+       struct bas_bc_state *ubc = bcs->hw.bas;
        struct urb *urb;
-       struct bas_bc_state *ubc;
        int j, k;
        int rc;
 
-       IFNULLRETVAL(bcs, -EFAULT);
-       ubc = bcs->hw.bas;
-       IFNULLRETVAL(ubc, -EFAULT);
-
        /* initialize L2 reception */
        if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
                bcs->inputstate |= INS_flag_hunt;
@@ -955,8 +911,6 @@ static void stopurbs(struct bas_bc_state *ubc)
 {
        int k, rc;
 
-       IFNULLRET(ubc);
-
        atomic_set(&ubc->running, 0);
 
        for (k = 0; k < BAS_INURBS; ++k) {
@@ -988,17 +942,11 @@ static void stopurbs(struct bas_bc_state *ubc)
  */
 static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
 {
-       struct urb *urb;
-       struct bas_bc_state *ubc;
+       struct urb *urb = ucx->urb;
+       struct bas_bc_state *ubc = ucx->bcs->hw.bas;
        struct usb_iso_packet_descriptor *ifd;
        int corrbytes, nframe, rc;
-
-       IFNULLRETVAL(ucx, -EFAULT);
-       urb = ucx->urb;
-       IFNULLRETVAL(urb, -EFAULT);
-       IFNULLRETVAL(ucx->bcs, -EFAULT);
-       ubc = ucx->bcs->hw.bas;
-       IFNULLRETVAL(ubc, -EFAULT);
+       unsigned long flags;
 
        /* urb->dev is clobbered by USB subsystem */
        urb->dev = ucx->bcs->cs->hw.bas->udev;
@@ -1045,7 +993,11 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
                ifd->actual_length = 0;
        }
        if ((urb->number_of_packets = nframe) > 0) {
-               if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
+               spin_lock_irqsave(&ucx->bcs->cs->lock, flags);
+               rc = ucx->bcs->cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
+               spin_unlock_irqrestore(&ucx->bcs->cs->lock, flags);
+
+               if (rc) {
                        dev_err(ucx->bcs->cs->dev,
                                "could not submit isochronous write URB: %s\n",
                                get_usb_statmsg(rc));
@@ -1065,9 +1017,9 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
  */
 static void write_iso_tasklet(unsigned long data)
 {
-       struct bc_state *bcs;
-       struct bas_bc_state *ubc;
-       struct cardstate *cs;
+       struct bc_state *bcs = (struct bc_state *) data;
+       struct bas_bc_state *ubc = bcs->hw.bas;
+       struct cardstate *cs = bcs->cs;
        struct isow_urbctx_t *done, *next, *ovfl;
        struct urb *urb;
        struct usb_iso_packet_descriptor *ifd;
@@ -1077,20 +1029,8 @@ static void write_iso_tasklet(unsigned long data)
        struct sk_buff *skb;
        int len;
 
-       bcs = (struct bc_state *) data;
-       IFNULLRET(bcs);
-       ubc = bcs->hw.bas;
-       IFNULLRET(ubc);
-       cs = bcs->cs;
-       IFNULLRET(cs);
-
        /* loop while completed URBs arrive in time */
        for (;;) {
-               if (unlikely(!atomic_read(&cs->connected))) {
-                       warn("%s: disconnected", __func__);
-                       return;
-               }
-
                if (unlikely(!(atomic_read(&ubc->running)))) {
                        gig_dbg(DEBUG_ISO, "%s: not running", __func__);
                        return;
@@ -1237,28 +1177,16 @@ static void write_iso_tasklet(unsigned long data)
  */
 static void read_iso_tasklet(unsigned long data)
 {
-       struct bc_state *bcs;
-       struct bas_bc_state *ubc;
-       struct cardstate *cs;
+       struct bc_state *bcs = (struct bc_state *) data;
+       struct bas_bc_state *ubc = bcs->hw.bas;
+       struct cardstate *cs = bcs->cs;
        struct urb *urb;
        char *rcvbuf;
        unsigned long flags;
        int totleft, numbytes, offset, frame, rc;
 
-       bcs = (struct bc_state *) data;
-       IFNULLRET(bcs);
-       ubc = bcs->hw.bas;
-       IFNULLRET(ubc);
-       cs = bcs->cs;
-       IFNULLRET(cs);
-
        /* loop while more completed URBs arrive in the meantime */
        for (;;) {
-               if (unlikely(!atomic_read(&cs->connected))) {
-                       warn("%s: disconnected", __func__);
-                       return;
-               }
-
                /* retrieve URB */
                spin_lock_irqsave(&ubc->isoinlock, flags);
                if (!(urb = ubc->isoindone)) {
@@ -1362,7 +1290,10 @@ static void read_iso_tasklet(unsigned long data)
                urb->dev = bcs->cs->hw.bas->udev;
                urb->transfer_flags = URB_ISO_ASAP;
                urb->number_of_packets = BAS_NUMFRAMES;
-               if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
+               spin_lock_irqsave(&cs->lock, flags);
+               rc = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
+               spin_unlock_irqrestore(&cs->lock, flags);
+               if (rc) {
                        dev_err(cs->dev,
                                "could not resubmit isochronous read URB: %s\n",
                                get_usb_statmsg(rc));
@@ -1383,15 +1314,10 @@ static void read_iso_tasklet(unsigned long data)
 static void req_timeout(unsigned long data)
 {
        struct bc_state *bcs = (struct bc_state *) data;
-       struct bas_cardstate *ucs;
+       struct bas_cardstate *ucs = bcs->cs->hw.bas;
        int pending;
        unsigned long flags;
 
-       IFNULLRET(bcs);
-       IFNULLRET(bcs->cs);
-       ucs = bcs->cs->hw.bas;
-       IFNULLRET(ucs);
-
        check_pending(ucs);
 
        spin_lock_irqsave(&ucs->lock, flags);
@@ -1441,14 +1367,9 @@ static void req_timeout(unsigned long data)
  */
 static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
 {
-       struct bas_cardstate *ucs;
+       struct bas_cardstate *ucs = urb->context;
        unsigned long flags;
 
-       IFNULLRET(urb);
-       IFNULLRET(urb->context);
-       IFNULLRET(cardstate);
-
-       ucs = (struct bas_cardstate *) urb->context;
        spin_lock_irqsave(&ucs->lock, flags);
        if (urb->status && ucs->pending) {
                dev_err(&ucs->interface->dev,
@@ -1482,16 +1403,10 @@ static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
  */
 static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
 {
-       struct bas_cardstate *ucs;
+       struct bas_cardstate *ucs = bcs->cs->hw.bas;
        int ret;
        unsigned long flags;
 
-       IFNULLRETVAL(bcs, -EINVAL);
-       IFNULLRETVAL(bcs->cs, -EINVAL);
-       ucs = bcs->cs->hw.bas;
-       IFNULLRETVAL(ucs, -EINVAL);
-       IFNULLRETVAL(ucs->urb_ctrl, -EINVAL);
-
        gig_dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val);
 
        spin_lock_irqsave(&ucs->lock, flags);
@@ -1551,8 +1466,6 @@ static int gigaset_init_bchannel(struct bc_state *bcs)
 {
        int req, ret;
 
-       IFNULLRETVAL(bcs, -EINVAL);
-
        if ((ret = starturbs(bcs)) < 0) {
                dev_err(bcs->cs->dev,
                        "could not start isochronous I/O for channel %d\n",
@@ -1585,8 +1498,6 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
 {
        int req, ret;
 
-       IFNULLRETVAL(bcs, -EINVAL);
-
        if (!(atomic_read(&bcs->cs->hw.bas->basstate) &
              (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
                /* channel not running: just signal common.c */
@@ -1613,11 +1524,7 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
  */
 static void complete_cb(struct cardstate *cs)
 {
-       struct cmdbuf_t *cb;
-
-       IFNULLRET(cs);
-       cb = cs->cmdbuf;
-       IFNULLRET(cb);
+       struct cmdbuf_t *cb = cs->cmdbuf;
 
        /* unqueue completed buffer */
        cs->cmdbytes -= cs->curlen;
@@ -1649,15 +1556,9 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len);
  */
 static void write_command_callback(struct urb *urb, struct pt_regs *regs)
 {
-       struct cardstate *cs;
+       struct cardstate *cs = urb->context;
+       struct bas_cardstate *ucs = cs->hw.bas;
        unsigned long flags;
-       struct bas_cardstate *ucs;
-
-       IFNULLRET(urb);
-       cs = (struct cardstate *) urb->context;
-       IFNULLRET(cs);
-       ucs = cs->hw.bas;
-       IFNULLRET(ucs);
 
        /* check status */
        switch (urb->status) {
@@ -1709,11 +1610,7 @@ static void write_command_callback(struct urb *urb, struct pt_regs *regs)
 static void atrdy_timeout(unsigned long data)
 {
        struct cardstate *cs = (struct cardstate *) data;
-       struct bas_cardstate *ucs;
-
-       IFNULLRET(cs);
-       ucs = cs->hw.bas;
-       IFNULLRET(ucs);
+       struct bas_cardstate *ucs = cs->hw.bas;
 
        dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n");
 
@@ -1736,14 +1633,10 @@ static void atrdy_timeout(unsigned long data)
  */
 static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
 {
-       struct bas_cardstate *ucs;
+       struct bas_cardstate *ucs = cs->hw.bas;
+       unsigned long flags;
        int ret;
 
-       IFNULLRETVAL(cs, -EFAULT);
-       ucs = cs->hw.bas;
-       IFNULLRETVAL(ucs, -EFAULT);
-       IFNULLRETVAL(ucs->urb_cmd_out, -EFAULT);
-
        gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len);
 
        if (ucs->urb_cmd_out->status == -EINPROGRESS) {
@@ -1762,7 +1655,11 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
                             (unsigned char*) &ucs->dr_cmd_out, buf, len,
                             write_command_callback, cs);
 
-       if ((ret = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC)) != 0) {
+       spin_lock_irqsave(&cs->lock, flags);
+       ret = cs->connected ? usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC) : -ENODEV;
+       spin_unlock_irqrestore(&cs->lock, flags);
+
+       if (ret) {
                dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n",
                        get_usb_statmsg(ret));
                return ret;
@@ -1795,15 +1692,11 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
 static int start_cbsend(struct cardstate *cs)
 {
        struct cmdbuf_t *cb;
-       struct bas_cardstate *ucs;
+       struct bas_cardstate *ucs = cs->hw.bas;
        unsigned long flags;
        int rc;
        int retval = 0;
 
-       IFNULLRETVAL(cs, -EFAULT);
-       ucs = cs->hw.bas;
-       IFNULLRETVAL(ucs, -EFAULT);
-
        /* check if AT channel is open */
        if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) {
                gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open");
@@ -1863,12 +1756,7 @@ static int gigaset_write_cmd(struct cardstate *cs,
 
        gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
                             DEBUG_TRANSCMD : DEBUG_LOCKCMD,
-                          "CMD Transmit", len, buf, 0);
-
-       if (unlikely(!atomic_read(&cs->connected))) {
-               err("%s: disconnected", __func__);
-               return -ENODEV;
-       }
+                          "CMD Transmit", len, buf);
 
        if (len <= 0)
                return 0;                       /* nothing to do */
@@ -2084,17 +1972,12 @@ static int gigaset_initcshw(struct cardstate *cs)
  */
 static void freeurbs(struct cardstate *cs)
 {
-       struct bas_cardstate *ucs;
+       struct bas_cardstate *ucs = cs->hw.bas;
        struct bas_bc_state *ubc;
        int i, j;
 
-       IFNULLRET(cs);
-       ucs = cs->hw.bas;
-       IFNULLRET(ucs);
-
        for (j = 0; j < 2; ++j) {
                ubc = cs->bcs[j].hw.bas;
-               IFNULLCONT(ubc);
                for (i = 0; i < BAS_OUTURBS; ++i)
                        if (ubc->isoouturbs[i].urb) {
                                usb_kill_urb(ubc->isoouturbs[i].urb);
@@ -2160,8 +2043,6 @@ static int gigaset_probe(struct usb_interface *interface,
        int i, j;
        int ret;
 
-       IFNULLRETVAL(udev, -ENODEV);
-
        gig_dbg(DEBUG_ANY,
                "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
                __func__, le16_to_cpu(udev->descriptor.idVendor),
@@ -2217,7 +2098,7 @@ static int gigaset_probe(struct usb_interface *interface,
        usb_get_dev(udev);
        ucs->udev = udev;
        ucs->interface = interface;
-       cs->dev = &udev->dev;
+       cs->dev = &interface->dev;
 
        /* allocate URBs:
         * - one for the interrupt pipe
@@ -2289,18 +2170,18 @@ static int gigaset_probe(struct usb_interface *interface,
        /* tell common part that the device is ready */
        if (startmode == SM_LOCKED)
                atomic_set(&cs->mstate, MS_LOCKED);
-       if (!gigaset_start(cs))
-               goto error;
 
        /* save address of controller structure */
        usb_set_intfdata(interface, cs);
 
-       /* set up device sysfs */
-       gigaset_init_dev_sysfs(interface);
+       if (!gigaset_start(cs))
+               goto error;
+
        return 0;
 
 error:
        freeurbs(cs);
+       usb_set_intfdata(interface, NULL);
        gigaset_unassign(cs);
        return -ENODEV;
 }
@@ -2313,23 +2194,22 @@ static void gigaset_disconnect(struct usb_interface *interface)
        struct cardstate *cs;
        struct bas_cardstate *ucs;
 
-       /* clear device sysfs */
-       gigaset_free_dev_sysfs(interface);
-
        cs = usb_get_intfdata(interface);
-       usb_set_intfdata(interface, NULL);
 
-       IFNULLRET(cs);
        ucs = cs->hw.bas;
-       IFNULLRET(ucs);
 
-       dev_info(cs->dev, "disconnecting GigaSet base");
+       dev_info(cs->dev, "disconnecting Gigaset base\n");
        gigaset_stop(cs);
        freeurbs(cs);
+       usb_set_intfdata(interface, NULL);
        kfree(ucs->rcvbuf);
        ucs->rcvbuf = NULL;
        ucs->rcvbuf_size = 0;
        atomic_set(&ucs->basstate, 0);
+       usb_put_dev(ucs->udev);
+       ucs->interface = NULL;
+       ucs->udev = NULL;
+       cs->dev = NULL;
        gigaset_unassign(cs);
 }