X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fisdn%2Fgigaset%2Fusb-gigaset.c;h=6e05d9d4a51ad13ad0acd55a4b9b9c6a26b3eaa9;hb=ac7f6b5e44cb0982b98c31fa33298ba73fb5dcfc;hp=6ae5df5f2b6adfb4a15c741a5cc78bc7d46d0dad;hpb=01371500b245ae63f542d74140a3d8ccb74d0318;p=powerpc.git diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 6ae5df5f2b..6e05d9d4a5 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -1,7 +1,7 @@ /* * USB driver for Gigaset 307x directly or using M105 Data. * - * Copyright (c) 2001 by Stefan Eilers + * Copyright (c) 2001 by Stefan Eilers * and Hansjoerg Lipp . * * This driver was derived from the USB skeleton driver by @@ -25,7 +25,7 @@ #include /* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp , Stefan Eilers " +#define DRIVER_AUTHOR "Hansjoerg Lipp , Stefan Eilers" #define DRIVER_DESC "USB Driver for Gigaset 307x using M105" /* Module parameters */ @@ -41,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 @@ -371,13 +370,14 @@ static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs) int r; unsigned numbytes; unsigned char *src; - - if (!atomic_read(&cs->connected)) { - err("%s: disconnected", __func__); - return; - } + unsigned long flags; if (!urb->status) { + if (!cs->connected) { + err("%s: disconnected", __func__); /* should never happen */ + return; + } + numbytes = urb->actual_length; if (numbytes) { @@ -399,12 +399,19 @@ static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs) /* The urb might have been killed. */ gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", __func__, urb->status); - if (urb->status != -ENOENT) /* not killed */ + if (urb->status != -ENOENT) { /* not killed */ + if (!cs->connected) { + err("%s: disconnected", __func__); /* should never happen */ + return; + } resubmit = 1; + } } 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) dev_err(cs->dev, "error %d when resubmitting urb.\n", -r); @@ -416,21 +423,22 @@ static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs) static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs) { struct cardstate *cs = urb->context; + unsigned long flags; -#ifdef CONFIG_GIGASET_DEBUG - if (!atomic_read(&cs->connected)) { - err("%s: not connected", __func__); - return; - } -#endif if (urb->status) 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) @@ -465,6 +473,8 @@ 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), @@ -474,14 +484,15 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) cb->offset += count; cb->len -= count; atomic_set(&ucs->busy, 1); - gig_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); - dev_err(cs->dev, - "could not submit urb (error %d)\n", - -status); + err("could not submit urb (error %d)\n", + -status); cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */ } @@ -502,11 +513,6 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, DEBUG_TRANSCMD : DEBUG_LOCKCMD, "CMD Transmit", len, buf); - if (!atomic_read(&cs->connected)) { - err("%s: not connected", __func__); - return -ENODEV; - } - if (len <= 0) return 0; @@ -533,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; } @@ -629,6 +638,7 @@ static int write_modem(struct cardstate *cs) int count; struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ struct usb_cardstate *ucs = cs->hw.usb; + unsigned long flags; gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); @@ -644,20 +654,27 @@ 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); gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); - ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + 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); + if (ret) { - dev_err(cs->dev, "could not submit urb (error %d)\n", -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? @@ -692,8 +709,8 @@ static int gigaset_probe(struct usb_interface *interface, 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... */ @@ -816,9 +833,6 @@ error: return retval; } -/** - * skel_disconnect - */ static void gigaset_disconnect(struct usb_interface *interface) { struct cardstate *cs; @@ -881,8 +895,7 @@ 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) + &ops, THIS_MODULE)) == NULL) goto error; /* allocate memory for our device state and intialize it */