diff options
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/act2000/module.c | 22 | ||||
-rw-r--r-- | drivers/isdn/gigaset/asyncdata.c | 8 | ||||
-rw-r--r-- | drivers/isdn/gigaset/bas-gigaset.c | 423 | ||||
-rw-r--r-- | drivers/isdn/gigaset/common.c | 135 | ||||
-rw-r--r-- | drivers/isdn/gigaset/ev-layer.c | 106 | ||||
-rw-r--r-- | drivers/isdn/gigaset/gigaset.h | 45 | ||||
-rw-r--r-- | drivers/isdn/gigaset/interface.c | 19 | ||||
-rw-r--r-- | drivers/isdn/gigaset/isocdata.c | 51 | ||||
-rw-r--r-- | drivers/isdn/gigaset/ser-gigaset.c | 20 | ||||
-rw-r--r-- | drivers/isdn/gigaset/usb-gigaset.c | 206 | ||||
-rw-r--r-- | drivers/isdn/hardware/eicon/debug.c | 2 | ||||
-rw-r--r-- | drivers/isdn/hardware/eicon/debuglib.c | 2 | ||||
-rw-r--r-- | drivers/isdn/hardware/eicon/debuglib.h | 2 | ||||
-rw-r--r-- | drivers/isdn/hardware/eicon/di.c | 2 | ||||
-rw-r--r-- | drivers/isdn/hardware/eicon/diva.c | 5 | ||||
-rw-r--r-- | drivers/isdn/hardware/eicon/message.c | 4 | ||||
-rw-r--r-- | drivers/isdn/hisax/avm_pci.c | 8 | ||||
-rw-r--r-- | drivers/isdn/hysdn/hycapi.c | 2 | ||||
-rw-r--r-- | drivers/isdn/i4l/isdn_tty.c | 1 | ||||
-rw-r--r-- | drivers/isdn/i4l/isdn_ttyfax.c | 2 | ||||
-rw-r--r-- | drivers/isdn/icn/icn.c | 22 | ||||
-rw-r--r-- | drivers/isdn/isdnloop/isdnloop.c | 16 |
22 files changed, 628 insertions, 475 deletions
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index ee2b0b9f8f4..8325022e2be 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c @@ -310,7 +310,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) } break; case ISDN_CMD_DIAL: - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x0f))) break; @@ -339,7 +339,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) } return ret; case ISDN_CMD_ACCEPTD: - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x0f))) break; @@ -347,11 +347,11 @@ act2000_command(act2000_card * card, isdn_ctrl * c) actcapi_select_b2_protocol_req(card, chan); return 0; case ISDN_CMD_ACCEPTB: - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; return 0; case ISDN_CMD_HANGUP: - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x0f))) break; @@ -366,7 +366,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) } return 0; case ISDN_CMD_SETEAZ: - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x0f))) break; @@ -386,7 +386,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) actcapi_listen_req(card); return 0; case ISDN_CMD_CLREAZ: - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x0f))) break; @@ -394,14 +394,14 @@ act2000_command(act2000_card * card, isdn_ctrl * c) actcapi_listen_req(card); return 0; case ISDN_CMD_SETL2: - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x0f))) break; chan->l2prot = (c->arg >> 8); return 0; case ISDN_CMD_SETL3: - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) { printk(KERN_WARNING "L3 protocol unknown\n"); @@ -524,7 +524,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) act2000_card *card = act2000_findcard(id); if (card) { - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; return (len); } @@ -539,7 +539,7 @@ if_readstatus(u_char __user * buf, int len, int id, int channel) act2000_card *card = act2000_findcard(id); if (card) { - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; return (act2000_readstatus(buf, len, card)); } @@ -554,7 +554,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) act2000_card *card = act2000_findcard(id); if (card) { - if (!card->flags & ACT2000_FLAGS_RUNNING) + if (!(card->flags & ACT2000_FLAGS_RUNNING)) return -ENODEV; return (act2000_sendbuf(card, channel, ack, skb)); } diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 00a3be5b862..091deb9d1c4 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -350,8 +350,8 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) unsigned char *src, c; int procbytes; - head = atomic_read(&inbuf->head); - tail = atomic_read(&inbuf->tail); + head = inbuf->head; + tail = inbuf->tail; gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); if (head != tail) { @@ -361,7 +361,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); while (numbytes) { - if (atomic_read(&cs->mstate) == MS_LOCKED) { + if (cs->mstate == MS_LOCKED) { procbytes = lock_loop(src, numbytes, inbuf); src += procbytes; numbytes -= procbytes; @@ -436,7 +436,7 @@ nextbyte: } gig_dbg(DEBUG_INTR, "setting head to %u", head); - atomic_set(&inbuf->head, head); + inbuf->head = head; } } EXPORT_SYMBOL_GPL(gigaset_m10x_input); diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index af7648274b3..5255b5e20e1 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -73,6 +73,14 @@ static int gigaset_probe(struct usb_interface *interface, /* Function will be called if the device is unplugged */ static void gigaset_disconnect(struct usb_interface *interface); +/* functions called before/after suspend */ +static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); +static int gigaset_resume(struct usb_interface *intf); + +/* functions called before/after device reset */ +static int gigaset_pre_reset(struct usb_interface *intf); +static int gigaset_post_reset(struct usb_interface *intf); + static int atread_submit(struct cardstate *, int); static void stopurbs(struct bas_bc_state *); static int req_submit(struct bc_state *, int, int, int); @@ -105,8 +113,9 @@ struct bas_cardstate { unsigned char int_in_buf[3]; spinlock_t lock; /* locks all following */ - atomic_t basstate; /* bitmap (BS_*) */ + int basstate; /* bitmap (BS_*) */ int pending; /* uncompleted base request */ + wait_queue_head_t waitqueue; int rcvbuf_size; /* size of AT receive buffer */ /* 0: no receive in progress */ int retry_cmd_in; /* receive req retry count */ @@ -121,10 +130,10 @@ struct bas_cardstate { #define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ +#define BS_SUSPEND 0x100 /* USB port suspended */ static struct gigaset_driver *driver = NULL; -static struct cardstate *cardstate = NULL; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { @@ -132,6 +141,11 @@ static struct usb_driver gigaset_usb_driver = { .probe = gigaset_probe, .disconnect = gigaset_disconnect, .id_table = gigaset_table, + .suspend = gigaset_suspend, + .resume = gigaset_resume, + .reset_resume = gigaset_post_reset, + .pre_reset = gigaset_pre_reset, + .post_reset = gigaset_post_reset, }; /* get message text for usb_submit_urb return code @@ -248,12 +262,12 @@ static inline void dump_urb(enum debuglevel level, const char *tag, if (urb) { gig_dbg(level, " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " - "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,", + "hcpriv=0x%08lx, transfer_flags=0x%x,", (unsigned long) urb->dev, usb_pipetype_str(urb->pipe), usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), usb_pipein(urb->pipe) ? "in" : "out", - urb->status, (unsigned long) urb->hcpriv, + (unsigned long) urb->hcpriv, urb->transfer_flags); gig_dbg(level, " transfer_buffer=0x%08lx[%d], actual_length=%d, " @@ -355,27 +369,27 @@ static void check_pending(struct bas_cardstate *ucs) case 0: break; case HD_OPEN_ATCHANNEL: - if (atomic_read(&ucs->basstate) & BS_ATOPEN) + if (ucs->basstate & BS_ATOPEN) ucs->pending = 0; break; case HD_OPEN_B1CHANNEL: - if (atomic_read(&ucs->basstate) & BS_B1OPEN) + if (ucs->basstate & BS_B1OPEN) ucs->pending = 0; break; case HD_OPEN_B2CHANNEL: - if (atomic_read(&ucs->basstate) & BS_B2OPEN) + if (ucs->basstate & BS_B2OPEN) ucs->pending = 0; break; case HD_CLOSE_ATCHANNEL: - if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) + if (!(ucs->basstate & BS_ATOPEN)) ucs->pending = 0; break; case HD_CLOSE_B1CHANNEL: - if (!(atomic_read(&ucs->basstate) & BS_B1OPEN)) + if (!(ucs->basstate & BS_B1OPEN)) ucs->pending = 0; break; case HD_CLOSE_B2CHANNEL: - if (!(atomic_read(&ucs->basstate) & BS_B2OPEN)) + if (!(ucs->basstate & BS_B2OPEN)) ucs->pending = 0; break; case HD_DEVICE_INIT_ACK: /* no reply expected */ @@ -441,8 +455,8 @@ inline static int update_basstate(struct bas_cardstate *ucs, int state; spin_lock_irqsave(&ucs->lock, flags); - state = atomic_read(&ucs->basstate); - atomic_set(&ucs->basstate, (state & ~clear) | set); + state = ucs->basstate; + ucs->basstate = (state & ~clear) | set; spin_unlock_irqrestore(&ucs->lock, flags); return state; } @@ -459,11 +473,13 @@ static void read_ctrl_callback(struct urb *urb) struct inbuf_t *inbuf = urb->context; struct cardstate *cs = inbuf->cs; struct bas_cardstate *ucs = cs->hw.bas; + int status = urb->status; int have_data = 0; unsigned numbytes; int rc; update_basstate(ucs, 0, BS_ATRDPEND); + wake_up(&ucs->waitqueue); if (!ucs->rcvbuf_size) { dev_warn(cs->dev, "%s: no receive in progress\n", __func__); @@ -472,7 +488,7 @@ static void read_ctrl_callback(struct urb *urb) del_timer(&ucs->timer_cmd_in); - switch (urb->status) { + switch (status) { case 0: /* normal completion */ numbytes = urb->actual_length; if (unlikely(numbytes != ucs->rcvbuf_size)) { @@ -506,12 +522,12 @@ static void read_ctrl_callback(struct urb *urb) case -ESHUTDOWN: /* device shut down */ /* no action necessary */ gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(urb->status)); + __func__, get_usb_statmsg(status)); break; default: /* severe trouble */ dev_warn(cs->dev, "control read: %s\n", - get_usb_statmsg(urb->status)); + get_usb_statmsg(status)); if (ucs->retry_cmd_in++ < BAS_RETRY) { dev_notice(cs->dev, "control read: retry %d\n", ucs->retry_cmd_in); @@ -550,17 +566,28 @@ static void read_ctrl_callback(struct urb *urb) static int atread_submit(struct cardstate *cs, int timeout) { struct bas_cardstate *ucs = cs->hw.bas; + int basstate; int ret; gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", ucs->rcvbuf_size); - if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) { + basstate = update_basstate(ucs, BS_ATRDPEND, 0); + if (basstate & BS_ATRDPEND) { dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: URB busy\n"); return -EBUSY; } + if (basstate & BS_SUSPEND) { + dev_notice(cs->dev, + "HD_READ_ATMESSAGE not submitted, " + "suspend in progress\n"); + update_basstate(ucs, 0, BS_ATRDPEND); + /* treat like disconnect */ + return -ENODEV; + } + ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; ucs->dr_cmd_in.wValue = 0; @@ -601,12 +628,13 @@ static void read_int_callback(struct urb *urb) struct cardstate *cs = urb->context; struct bas_cardstate *ucs = cs->hw.bas; struct bc_state *bcs; + int status = urb->status; unsigned long flags; int rc; unsigned l; int channel; - switch (urb->status) { + switch (status) { case 0: /* success */ break; case -ENOENT: /* cancelled */ @@ -614,7 +642,7 @@ static void read_int_callback(struct urb *urb) case -EINPROGRESS: /* pending */ /* ignore silently */ gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(urb->status)); + __func__, get_usb_statmsg(status)); return; case -ENODEV: /* device removed */ case -ESHUTDOWN: /* device shut down */ @@ -623,7 +651,7 @@ static void read_int_callback(struct urb *urb) return; default: /* severe trouble */ dev_warn(cs->dev, "interrupt read: %s\n", - get_usb_statmsg(urb->status)); + get_usb_statmsg(status)); //FIXME corrective action? resubmission always ok? goto resubmit; } @@ -745,6 +773,7 @@ static void read_int_callback(struct urb *urb) } check_pending(ucs); + wake_up(&ucs->waitqueue); resubmit: rc = usb_submit_urb(urb, GFP_ATOMIC); @@ -766,17 +795,18 @@ static void read_iso_callback(struct urb *urb) { struct bc_state *bcs; struct bas_bc_state *ubc; + int status = urb->status; unsigned long flags; int i, rc; /* status codes not worth bothering the tasklet with */ - if (unlikely(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -EINPROGRESS || - urb->status == -ENODEV || - urb->status == -ESHUTDOWN)) { + if (unlikely(status == -ENOENT || + status == -ECONNRESET || + status == -EINPROGRESS || + status == -ENODEV || + status == -ESHUTDOWN)) { gig_dbg(DEBUG_ISO, "%s: %s", - __func__, get_usb_statmsg(urb->status)); + __func__, get_usb_statmsg(status)); return; } @@ -787,10 +817,11 @@ static void read_iso_callback(struct urb *urb) if (likely(ubc->isoindone == NULL)) { /* pass URB to tasklet */ ubc->isoindone = urb; + ubc->isoinstatus = status; tasklet_schedule(&ubc->rcvd_tasklet); } else { /* tasklet still busy, drop data and resubmit URB */ - ubc->loststatus = urb->status; + ubc->loststatus = status; for (i = 0; i < BAS_NUMFRAMES; i++) { ubc->isoinlost += urb->iso_frame_desc[i].actual_length; if (unlikely(urb->iso_frame_desc[i].status != 0 && @@ -800,7 +831,7 @@ static void read_iso_callback(struct urb *urb) urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; } - if (likely(atomic_read(&ubc->running))) { + if (likely(ubc->running)) { /* urb->dev is clobbered by USB subsystem */ urb->dev = bcs->cs->hw.bas->udev; urb->transfer_flags = URB_ISO_ASAP; @@ -831,22 +862,24 @@ static void write_iso_callback(struct urb *urb) { struct isow_urbctx_t *ucx; struct bas_bc_state *ubc; + int status = urb->status; unsigned long flags; /* status codes not worth bothering the tasklet with */ - if (unlikely(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -EINPROGRESS || - urb->status == -ENODEV || - urb->status == -ESHUTDOWN)) { + if (unlikely(status == -ENOENT || + status == -ECONNRESET || + status == -EINPROGRESS || + status == -ENODEV || + status == -ESHUTDOWN)) { gig_dbg(DEBUG_ISO, "%s: %s", - __func__, get_usb_statmsg(urb->status)); + __func__, get_usb_statmsg(status)); return; } /* pass URB context to tasklet */ ucx = urb->context; ubc = ucx->bcs->hw.bas; + ucx->status = status; spin_lock_irqsave(&ubc->isooutlock, flags); ubc->isooutovfl = ubc->isooutdone; @@ -875,7 +908,7 @@ static int starturbs(struct bc_state *bcs) bcs->inputstate |= INS_flag_hunt; /* submit all isochronous input URBs */ - atomic_set(&ubc->running, 1); + ubc->running = 1; for (k = 0; k < BAS_INURBS; k++) { urb = ubc->isoinurbs[k]; if (!urb) { @@ -932,15 +965,15 @@ static int starturbs(struct bc_state *bcs) ubc->isoouturbs[k].limit = -1; } - /* submit two URBs, keep third one */ - for (k = 0; k < 2; ++k) { + /* keep one URB free, submit the others */ + for (k = 0; k < BAS_OUTURBS-1; ++k) { dump_urb(DEBUG_ISO, "Initial isoc write", urb); rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); if (rc != 0) goto error; } dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); - ubc->isooutfree = &ubc->isoouturbs[2]; + ubc->isooutfree = &ubc->isoouturbs[BAS_OUTURBS-1]; ubc->isooutdone = ubc->isooutovfl = NULL; return 0; error: @@ -958,7 +991,7 @@ static void stopurbs(struct bas_bc_state *ubc) { int k, rc; - atomic_set(&ubc->running, 0); + ubc->running = 0; for (k = 0; k < BAS_INURBS; ++k) { rc = usb_unlink_urb(ubc->isoinurbs[k]); @@ -1034,7 +1067,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) } break; } - ucx->limit = atomic_read(&ubc->isooutbuf->nextread); + ucx->limit = ubc->isooutbuf->nextread; ifd->status = 0; ifd->actual_length = 0; } @@ -1070,6 +1103,7 @@ static void write_iso_tasklet(unsigned long data) struct cardstate *cs = bcs->cs; struct isow_urbctx_t *done, *next, *ovfl; struct urb *urb; + int status; struct usb_iso_packet_descriptor *ifd; int offset; unsigned long flags; @@ -1080,7 +1114,7 @@ static void write_iso_tasklet(unsigned long data) /* loop while completed URBs arrive in time */ for (;;) { - if (unlikely(!(atomic_read(&ubc->running)))) { + if (unlikely(!(ubc->running))) { gig_dbg(DEBUG_ISO, "%s: not running", __func__); return; } @@ -1126,7 +1160,8 @@ static void write_iso_tasklet(unsigned long data) /* process completed URB */ urb = done->urb; - switch (urb->status) { + status = done->status; + switch (status) { case -EXDEV: /* partial completion */ gig_dbg(DEBUG_ISO, "%s: URB partially completed", __func__); @@ -1179,12 +1214,12 @@ static void write_iso_tasklet(unsigned long data) break; default: /* severe trouble */ dev_warn(cs->dev, "isochronous write: %s\n", - get_usb_statmsg(urb->status)); + get_usb_statmsg(status)); } /* mark the write buffer area covered by this URB as free */ if (done->limit >= 0) - atomic_set(&ubc->isooutbuf->read, done->limit); + ubc->isooutbuf->read = done->limit; /* mark URB as free */ spin_lock_irqsave(&ubc->isooutlock, flags); @@ -1233,6 +1268,7 @@ static void read_iso_tasklet(unsigned long data) struct bas_bc_state *ubc = bcs->hw.bas; struct cardstate *cs = bcs->cs; struct urb *urb; + int status; char *rcvbuf; unsigned long flags; int totleft, numbytes, offset, frame, rc; @@ -1245,6 +1281,7 @@ static void read_iso_tasklet(unsigned long data) spin_unlock_irqrestore(&ubc->isoinlock, flags); return; } + status = ubc->isoinstatus; ubc->isoindone = NULL; if (unlikely(ubc->loststatus != -EINPROGRESS)) { dev_warn(cs->dev, @@ -1256,15 +1293,15 @@ static void read_iso_tasklet(unsigned long data) } spin_unlock_irqrestore(&ubc->isoinlock, flags); - if (unlikely(!(atomic_read(&ubc->running)))) { + if (unlikely(!(ubc->running))) { gig_dbg(DEBUG_ISO, "%s: channel not running, " "dropped URB with status: %s", - __func__, get_usb_statmsg(urb->status)); + __func__, get_usb_statmsg(status)); return; } - switch (urb->status) { + switch (status) { case 0: /* normal completion */ break; case -EXDEV: /* inspect individual frames @@ -1276,7 +1313,7 @@ static void read_iso_tasklet(unsigned long data) case -ECONNRESET: case -EINPROGRESS: gig_dbg(DEBUG_ISO, "%s: %s", - __func__, get_usb_statmsg(urb->status)); + __func__, get_usb_statmsg(status)); continue; /* -> skip */ case -EPIPE: dev_err(cs->dev, "isochronous read stalled\n"); @@ -1284,7 +1321,7 @@ static void read_iso_tasklet(unsigned long data) continue; /* -> skip */ default: /* severe trouble */ dev_warn(cs->dev, "isochronous read: %s\n", - get_usb_statmsg(urb->status)); + get_usb_statmsg(status)); goto error; } @@ -1406,6 +1443,8 @@ static void req_timeout(unsigned long data) dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", pending); } + + wake_up(&ucs->waitqueue); } /* write_ctrl_callback @@ -1418,11 +1457,12 @@ static void req_timeout(unsigned long data) static void write_ctrl_callback(struct urb *urb) { struct bas_cardstate *ucs = urb->context; + int status = urb->status; int rc; unsigned long flags; /* check status */ - switch (urb->status) { + switch (status) { case 0: /* normal completion */ spin_lock_irqsave(&ucs->lock, flags); switch (ucs->pending) { @@ -1441,20 +1481,22 @@ static void write_ctrl_callback(struct urb *urb) case -ESHUTDOWN: /* device shut down */ /* ignore silently */ gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(urb->status)); + __func__, get_usb_statmsg(status)); break; default: /* any failure */ - if (++ucs->retry_ctrl > BAS_RETRY) { + /* don't retry if suspend requested */ + if (++ucs->retry_ctrl > BAS_RETRY || + (ucs->basstate & BS_SUSPEND)) { dev_err(&ucs->interface->dev, "control request 0x%02x failed: %s\n", ucs->dr_ctrl.bRequest, - get_usb_statmsg(urb->status)); + get_usb_statmsg(status)); break; /* give up */ } dev_notice(&ucs->interface->dev, "control request 0x%02x: %s, retry %d\n", - ucs->dr_ctrl.bRequest, get_usb_statmsg(urb->status), + ucs->dr_ctrl.bRequest, get_usb_statmsg(status), ucs->retry_ctrl); /* urb->dev is clobbered by USB subsystem */ urb->dev = ucs->udev; @@ -1474,6 +1516,7 @@ static void write_ctrl_callback(struct urb *urb) del_timer(&ucs->timer_ctrl); ucs->pending = 0; spin_unlock_irqrestore(&ucs->lock, flags); + wake_up(&ucs->waitqueue); } /* req_submit @@ -1548,37 +1591,46 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) */ static int gigaset_init_bchannel(struct bc_state *bcs) { + struct cardstate *cs = bcs->cs; int req, ret; unsigned long flags; - spin_lock_irqsave(&bcs->cs->lock, flags); - if (unlikely(!bcs->cs->connected)) { + spin_lock_irqsave(&cs->lock, flags); + if (unlikely(!cs->connected)) { gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); - spin_unlock_irqrestore(&bcs->cs->lock, flags); + spin_unlock_irqrestore(&cs->lock, flags); return -ENODEV; } + if (cs->hw.bas->basstate & BS_SUSPEND) { + dev_notice(cs->dev, + "not starting isochronous I/O, " + "suspend in progress\n"); + spin_unlock_irqrestore(&cs->lock, flags); + return -EHOSTUNREACH; + } + if ((ret = starturbs(bcs)) < 0) { - dev_err(bcs->cs->dev, + dev_err(cs->dev, "could not start isochronous I/O for channel B%d: %s\n", bcs->channel + 1, ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); if (ret != -ENODEV) error_hangup(bcs); - spin_unlock_irqrestore(&bcs->cs->lock, flags); + spin_unlock_irqrestore(&cs->lock, flags); return ret; } req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { - dev_err(bcs->cs->dev, "could not open channel B%d\n", + dev_err(cs->dev, "could not open channel B%d\n", bcs->channel + 1); stopurbs(bcs->hw.bas); if (ret != -ENODEV) error_hangup(bcs); } - spin_unlock_irqrestore(&bcs->cs->lock, flags); + spin_unlock_irqrestore(&cs->lock, flags); return ret; } @@ -1594,20 +1646,20 @@ static int gigaset_init_bchannel(struct bc_state *bcs) */ static int gigaset_close_bchannel(struct bc_state *bcs) { + struct cardstate *cs = bcs->cs; int req, ret; unsigned long flags; - spin_lock_irqsave(&bcs->cs->lock, flags); - if (unlikely(!bcs->cs->connected)) { - spin_unlock_irqrestore(&bcs->cs->lock, flags); + spin_lock_irqsave(&cs->lock, flags); + if (unlikely(!cs->connected)) { + spin_unlock_irqrestore(&cs->lock, flags); gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); return -ENODEV; } - if (!(atomic_read(&bcs->cs->hw.bas->basstate) & - (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { + if (!(cs->hw.bas->basstate & (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { /* channel not running: just signal common.c */ - spin_unlock_irqrestore(&bcs->cs->lock, flags); + spin_unlock_irqrestore(&cs->lock, flags); gigaset_bchannel_down(bcs); return 0; } @@ -1615,10 +1667,10 @@ static int gigaset_close_bchannel(struct bc_state *bcs) /* channel running: tell device to close it */ req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) - dev_err(bcs->cs->dev, "closing channel B%d failed\n", + dev_err(cs->dev, "closing channel B%d failed\n", bcs->channel + 1); - spin_unlock_irqrestore(&bcs->cs->lock, flags); + spin_unlock_irqrestore(&cs->lock, flags); return ret; } @@ -1665,12 +1717,14 @@ static void write_command_callback(struct urb *urb) { struct cardstate *cs = urb->context; struct bas_cardstate *ucs = cs->hw.bas; + int status = urb->status; unsigned long flags; update_basstate(ucs, 0, BS_ATWRPEND); + wake_up(&ucs->waitqueue); /* check status */ - switch (urb->status) { + switch (status) { case 0: /* normal completion */ break; case -ENOENT: /* cancelled */ @@ -1680,26 +1734,33 @@ static void write_command_callback(struct urb *urb) case -ESHUTDOWN: /* device shut down */ /* ignore silently */ gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(urb->status)); + __func__, get_usb_statmsg(status)); return; default: /* any failure */ if (++ucs->retry_cmd_out > BAS_RETRY) { dev_warn(cs->dev, "command write: %s, " "giving up after %d retries\n", - get_usb_statmsg(urb->status), + get_usb_statmsg(status), ucs->retry_cmd_out); break; } + if (ucs->basstate & BS_SUSPEND) { + dev_warn(cs->dev, + "command write: %s, " + "won't retry - suspend requested\n", + get_usb_statmsg(status)); + break; + } if (cs->cmdbuf == NULL) { dev_warn(cs->dev, "command write: %s, " "cannot retry - cmdbuf gone\n", - get_usb_statmsg(urb->status)); + get_usb_statmsg(status)); break; } dev_notice(cs->dev, "command write: %s, retry %d\n", - get_usb_statmsg(urb->status), ucs->retry_cmd_out); + get_usb_statmsg(status), ucs->retry_cmd_out); if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) /* resubmitted - bypass regular exit block */ return; @@ -1799,8 +1860,14 @@ static int start_cbsend(struct cardstate *cs) int rc; int retval = 0; + /* check if suspend requested */ + if (ucs->basstate & BS_SUSPEND) { + gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "suspending"); + return -EHOSTUNREACH; + } + /* check if AT channel is open */ - if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) { + if (!(ucs->basstate & BS_ATOPEN)) { gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); if (rc < 0) { @@ -1816,8 +1883,7 @@ static int start_cbsend(struct cardstate *cs) /* try to send first command in queue */ spin_lock_irqsave(&cs->cmdlock, flags); - while ((cb = cs->cmdbuf) != NULL && - atomic_read(&ucs->basstate) & BS_ATREADY) { + while ((cb = cs->cmdbuf) != NULL && (ucs->basstate & BS_ATREADY)) { ucs->retry_cmd_out = 0; rc = atwrite_submit(cs, cb->buf, cb->len); if (unlikely(rc)) { @@ -1855,7 +1921,7 @@ static int gigaset_write_cmd(struct cardstate *cs, unsigned long flags; int rc; - gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? + gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? DEBUG_TRANSCMD : DEBUG_LOCKCMD, "CMD Transmit", len, buf); @@ -1970,7 +2036,7 @@ static int gigaset_freebcshw(struct bc_state *bcs) return 0; /* kill URBs and tasklets before freeing - better safe than sorry */ - atomic_set(&ubc->running, 0); + ubc->running = 0; gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); for (i = 0; i < BAS_OUTURBS; ++i) { usb_kill_urb(ubc->isoouturbs[i].urb); @@ -2005,7 +2071,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) return 0; } - atomic_set(&ubc->running, 0); + ubc->running = 0; atomic_set(&ubc->corrbytes, 0); spin_lock_init(&ubc->isooutlock); for (i = 0; i < BAS_OUTURBS; ++i) { @@ -2050,7 +2116,7 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) { struct bas_bc_state *ubc = bcs->hw.bas; - atomic_set(&bcs->hw.bas->running, 0); + bcs->hw.bas->running = 0; atomic_set(&bcs->hw.bas->corrbytes, 0); bcs->hw.bas->numsub = 0; spin_lock_init(&ubc->isooutlock); @@ -2081,10 +2147,11 @@ static int gigaset_initcshw(struct cardstate *cs) spin_lock_init(&ucs->lock); ucs->pending = 0; - atomic_set(&ucs->basstate, 0); + ucs->basstate = 0; init_timer(&ucs->timer_ctrl); init_timer(&ucs->timer_atrdy); init_timer(&ucs->timer_cmd_in); + init_waitqueue_head(&ucs->waitqueue); return 1; } @@ -2102,7 +2169,7 @@ static void freeurbs(struct cardstate *cs) int i, j; gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); - for (j = 0; j < 2; ++j) { + for (j = 0; j < BAS_CHANNELS; ++j) { ubc = cs->bcs[j].hw.bas; for (i = 0; i < BAS_OUTURBS; ++i) { usb_kill_urb(ubc->isoouturbs[i].urb); @@ -2179,11 +2246,11 @@ static int gigaset_probe(struct usb_interface *interface, __func__, le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); - cs = gigaset_getunassignedcs(driver); - if (!cs) { - dev_err(&udev->dev, "no free cardstate\n"); + /* allocate memory for our device state and intialize it */ + cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode, + GIGASET_MODULENAME); + if (!cs) return -ENODEV; - } ucs = cs->hw.bas; /* save off device structure ptrs for later use */ @@ -2203,7 +2270,7 @@ static int gigaset_probe(struct usb_interface *interface, !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) goto allocerr; - for (j = 0; j < 2; ++j) { + for (j = 0; j < BAS_CHANNELS; ++j) { ubc = cs->bcs[j].hw.bas; for (i = 0; i < BAS_OUTURBS; ++i) if (!(ubc->isoouturbs[i].urb = @@ -2237,7 +2304,7 @@ 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); + cs->mstate = MS_LOCKED; /* save address of controller structure */ usb_set_intfdata(interface, cs); @@ -2252,7 +2319,7 @@ allocerr: error: freeurbs(cs); usb_set_intfdata(interface, NULL); - gigaset_unassign(cs); + gigaset_freecs(cs); return -ENODEV; } @@ -2272,11 +2339,10 @@ static void gigaset_disconnect(struct usb_interface *interface) dev_info(cs->dev, "disconnecting Gigaset base\n"); /* mark base as not ready, all channels disconnected */ - atomic_set(&ucs->basstate, 0); + ucs->basstate = 0; /* tell LL all channels are down */ - //FIXME shouldn't gigaset_stop() do this? - for (j = 0; j < 2; ++j) + for (j = 0; j < BAS_CHANNELS; ++j) gigaset_bchannel_down(cs->bcs + j); /* stop driver (common part) */ @@ -2295,9 +2361,113 @@ static void gigaset_disconnect(struct usb_interface *interface) ucs->interface = NULL; ucs->udev = NULL; cs->dev = NULL; - gigaset_unassign(cs); + gigaset_freecs(cs); } +/* gigaset_suspend + * This function is called before the USB connection is suspended. + */ +static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct cardstate *cs = usb_get_intfdata(intf); + struct bas_cardstate *ucs = cs->hw.bas; + int rc; + + /* set suspend flag; this stops AT command/response traffic */ + if (update_basstate(ucs, BS_SUSPEND, 0) & BS_SUSPEND) { + gig_dbg(DEBUG_SUSPEND, "already suspended"); + return 0; + } + + /* wait a bit for blocking conditions to go away */ + rc = wait_event_timeout(ucs->waitqueue, + !(ucs->basstate & + (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)), + BAS_TIMEOUT*HZ/10); + gig_dbg(DEBUG_SUSPEND, "wait_event_timeout() -> %d", rc); + + /* check for conditions preventing suspend */ + if (ucs->basstate & (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)) { + dev_warn(cs->dev, "cannot suspend:\n"); + if (ucs->basstate & BS_B1OPEN) + dev_warn(cs->dev, " B channel 1 open\n"); + if (ucs->basstate & BS_B2OPEN) + dev_warn(cs->dev, " B channel 2 open\n"); + if (ucs->basstate & BS_ATRDPEND) + dev_warn(cs->dev, " receiving AT reply\n"); + if (ucs->basstate & BS_ATWRPEND) + dev_warn(cs->dev, " sending AT command\n"); + update_basstate(ucs, 0, BS_SUSPEND); + return -EBUSY; + } + + /* close AT channel if open */ + if (ucs->basstate & BS_ATOPEN) { + gig_dbg(DEBUG_SUSPEND, "closing AT channel"); + rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, 0); + if (rc) { + update_basstate(ucs, 0, BS_SUSPEND); + return rc; + } + wait_event_timeout(ucs->waitqueue, !ucs->pending, + BAS_TIMEOUT*HZ/10); + /* in case of timeout, proceed anyway */ + } + + /* kill all URBs and timers that might still be pending */ + usb_kill_urb(ucs->urb_ctrl); + usb_kill_urb(ucs->urb_int_in); + del_timer_sync(&ucs->timer_ctrl); + + gig_dbg(DEBUG_SUSPEND, "suspend complete"); + return 0; +} + +/* gigaset_resume + * This function is called after the USB connection has been resumed. + */ +static int gigaset_resume(struct usb_interface *intf) +{ + struct cardstate *cs = usb_get_intfdata(intf); + struct bas_cardstate *ucs = cs->hw.bas; + int rc; + + /* resubmit interrupt URB for spontaneous messages from base */ + rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); + if (rc) { + dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", + get_usb_rcmsg(rc)); + return rc; + } + + /* clear suspend flag to reallow activity */ + update_basstate(ucs, 0, BS_SUSPEND); + + gig_dbg(DEBUG_SUSPEND, "resume complete"); + return 0; +} + +/* gigaset_pre_reset + * This function is called before the USB connection is reset. + */ +static int gigaset_pre_reset(struct usb_interface *intf) +{ + /* handle just like suspend */ + return gigaset_suspend(intf, PMSG_ON); +} + +/* gigaset_post_reset + * This function is called after the USB connection has been reset. + */ +static int gigaset_post_reset(struct usb_interface *intf) +{ + /* FIXME: send HD_DEVICE_INIT_ACK? */ + + /* resume operations */ + return gigaset_resume(intf); +} + + static const struct gigaset_ops gigops = { gigaset_write_cmd, gigaset_write_room, @@ -2330,12 +2500,6 @@ static int __init bas_gigaset_init(void) &gigops, THIS_MODULE)) == NULL) goto error; - /* allocate memory for our device state and intialize it */ - cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, - GIGASET_MODULENAME); - if (!cardstate) - goto error; - /* register this driver with the USB subsystem */ result = usb_register(&gigaset_usb_driver); if (result < 0) { @@ -2347,9 +2511,7 @@ static int __init bas_gigaset_init(void) info(DRIVER_DESC); return 0; -error: if (cardstate) - gigaset_freecs(cardstate); - cardstate = NULL; +error: if (driver) gigaset_freedriver(driver); driver = NULL; @@ -2361,43 +2523,50 @@ error: if (cardstate) */ static void __exit bas_gigaset_exit(void) { - struct bas_cardstate *ucs = cardstate->hw.bas; + struct bas_cardstate *ucs; + int i; gigaset_blockdriver(driver); /* => probe will fail * => no gigaset_start any more */ - gigaset_shutdown(cardstate); - /* from now on, no isdn callback should be possible */ - - /* close all still open channels */ - if (atomic_read(&ucs->basstate) & BS_B1OPEN) { - gig_dbg(DEBUG_INIT, "closing B1 channel"); - usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), - HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0, - NULL, 0, BAS_TIMEOUT); - } - if (atomic_read(&ucs->basstate) & BS_B2OPEN) { - gig_dbg(DEBUG_INIT, "closing B2 channel"); - usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), - HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0, - NULL, 0, BAS_TIMEOUT); - } - if (atomic_read(&ucs->basstate) & BS_ATOPEN) { - gig_dbg(DEBUG_INIT, "closing AT channel"); - usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), - HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0, - NULL, 0, BAS_TIMEOUT); + /* stop all connected devices */ + for (i = 0; i < driver->minors; i++) { + if (gigaset_shutdown(driver->cs + i) < 0) + continue; /* no device */ + /* from now on, no isdn callback should be possible */ + + /* close all still open channels */ + ucs = driver->cs[i].hw.bas; + if (ucs->basstate & BS_B1OPEN) { + gig_dbg(DEBUG_INIT, "closing B1 channel"); + usb_control_msg(ucs->udev, + usb_sndctrlpipe(ucs->udev, 0), + HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, + 0, 0, NULL, 0, BAS_TIMEOUT); + } + if (ucs->basstate & BS_B2OPEN) { + gig_dbg(DEBUG_INIT, "closing B2 channel"); + usb_control_msg(ucs->udev, + usb_sndctrlpipe(ucs->udev, 0), + HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, + 0, 0, NULL, 0, BAS_TIMEOUT); + } + if (ucs->basstate & BS_ATOPEN) { + gig_dbg(DEBUG_INIT, "closing AT channel"); + usb_control_msg(ucs->udev, + usb_sndctrlpipe(ucs->udev, 0), + HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, + 0, 0, NULL, 0, BAS_TIMEOUT); + } + ucs->basstate = 0; } - atomic_set(&ucs->basstate, 0); /* deregister this driver with the USB subsystem */ usb_deregister(&gigaset_usb_driver); /* this will call the disconnect-callback */ /* from now on, no disconnect/probe callback should be running */ - gigaset_freecs(cardstate); - cardstate = NULL; gigaset_freedriver(driver); driver = NULL; } diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index acd417197d0..aacedec4986 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -31,7 +31,6 @@ MODULE_PARM_DESC(debug, "debug level"); /* driver state flags */ #define VALID_MINOR 0x01 #define VALID_ID 0x02 -#define ASSIGNED 0x04 void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, size_t len, const unsigned char *buf) @@ -178,7 +177,7 @@ int gigaset_get_channel(struct bc_state *bcs) unsigned long flags; spin_lock_irqsave(&bcs->cs->lock, flags); - if (bcs->use_count) { + if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) { gig_dbg(DEBUG_ANY, "could not allocate channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); @@ -203,6 +202,7 @@ void gigaset_free_channel(struct bc_state *bcs) } --bcs->use_count; bcs->busy = 0; + module_put(bcs->cs->driver->owner); gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); } @@ -356,31 +356,28 @@ static struct cardstate *alloc_cs(struct gigaset_driver *drv) { unsigned long flags; unsigned i; + struct cardstate *cs; struct cardstate *ret = NULL; spin_lock_irqsave(&drv->lock, flags); + if (drv->blocked) + goto exit; for (i = 0; i < drv->minors; ++i) { - if (!(drv->flags[i] & VALID_MINOR)) { - if (try_module_get(drv->owner)) { - drv->flags[i] = VALID_MINOR; - ret = drv->cs + i; - } + cs = drv->cs + i; + if (!(cs->flags & VALID_MINOR)) { + cs->flags = VALID_MINOR; + ret = cs; break; } } +exit: 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); - if (drv->flags[cs->minor_index] & VALID_MINOR) - module_put(drv->owner); - drv->flags[cs->minor_index] = 0; - spin_unlock_irqrestore(&drv->lock, flags); + cs->flags = 0; } static void make_valid(struct cardstate *cs, unsigned mask) @@ -388,7 +385,7 @@ 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; + cs->flags |= mask; spin_unlock_irqrestore(&drv->lock, flags); } @@ -397,7 +394,7 @@ 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; + cs->flags &= ~mask; spin_unlock_irqrestore(&drv->lock, flags); } @@ -501,11 +498,11 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, struct cardstate *cs, int inputstate) /* inbuf->read must be allocated before! */ { - atomic_set(&inbuf->head, 0); - atomic_set(&inbuf->tail, 0); + inbuf->head = 0; + inbuf->tail = 0; inbuf->cs = cs; inbuf->bcs = bcs; /*base driver: NULL*/ - inbuf->rcvbuf = NULL; //FIXME + inbuf->rcvbuf = NULL; inbuf->inputstate = inputstate; } @@ -521,8 +518,8 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, return 0; bytesleft = numbytes; - tail = atomic_read(&inbuf->tail); - head = atomic_read(&inbuf->head); + tail = inbuf->tail; + head = inbuf->head; gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); while (bytesleft) { @@ -546,7 +543,7 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, src += n; } gig_dbg(DEBUG_INTR, "setting tail to %u", tail); - atomic_set(&inbuf->tail, tail); + inbuf->tail = tail; return numbytes != bytesleft; } EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); @@ -668,7 +665,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs); - atomic_set(&cs->commands_pending, 0); + cs->commands_pending = 0; cs->cur_at_seq = 0; cs->gotfwver = -1; cs->open_count = 0; @@ -688,8 +685,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, init_waitqueue_head(&cs->waitqueue); cs->waiting = 0; - atomic_set(&cs->mode, M_UNKNOWN); - atomic_set(&cs->mstate, MS_UNINITIALIZED); + cs->mode = M_UNKNOWN; + cs->mstate = MS_UNINITIALIZED; for (i = 0; i < channels; ++i) { gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); @@ -806,8 +803,8 @@ static void cleanup_cs(struct cardstate *cs) spin_lock_irqsave(&cs->lock, flags); - atomic_set(&cs->mode, M_UNKNOWN); - atomic_set(&cs->mstate, MS_UNINITIALIZED); + cs->mode = M_UNKNOWN; + cs->mstate = MS_UNINITIALIZED; clear_at_state(&cs->at_state); dealloc_at_states(cs); @@ -817,8 +814,8 @@ static void cleanup_cs(struct cardstate *cs) kfree(cs->inbuf->rcvbuf); cs->inbuf->rcvbuf = NULL; cs->inbuf->inputstate = INS_command; - atomic_set(&cs->inbuf->head, 0); - atomic_set(&cs->inbuf->tail, 0); + cs->inbuf->head = 0; + cs->inbuf->tail = 0; cb = cs->cmdbuf; while (cb) { @@ -832,7 +829,7 @@ static void cleanup_cs(struct cardstate *cs) cs->gotfwver = -1; cs->dle = 0; cs->cur_at_seq = 0; - atomic_set(&cs->commands_pending, 0); + cs->commands_pending = 0; cs->cbytes = 0; spin_unlock_irqrestore(&cs->lock, flags); @@ -862,7 +859,7 @@ int gigaset_start(struct cardstate *cs) cs->connected = 1; spin_unlock_irqrestore(&cs->lock, flags); - if (atomic_read(&cs->mstate) != MS_LOCKED) { + if (cs->mstate != MS_LOCKED) { cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); cs->ops->baud_rate(cs, B115200); cs->ops->set_line_ctrl(cs, CS8); @@ -893,10 +890,17 @@ error: } EXPORT_SYMBOL_GPL(gigaset_start); -void gigaset_shutdown(struct cardstate *cs) +/* 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 + */ +int gigaset_shutdown(struct cardstate *cs) { mutex_lock(&cs->mutex); + if (!(cs->flags & VALID_MINOR)) + return -1; + cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { @@ -913,6 +917,7 @@ void gigaset_shutdown(struct cardstate *cs) exit: mutex_unlock(&cs->mutex); + return 0; } EXPORT_SYMBOL_GPL(gigaset_shutdown); @@ -954,13 +959,11 @@ struct cardstate *gigaset_get_cs_by_id(int id) list_for_each_entry(drv, &drivers, list) { spin_lock(&drv->lock); for (i = 0; i < drv->minors; ++i) { - if (drv->flags[i] & VALID_ID) { - cs = drv->cs + i; - if (cs->myid == id) - ret = cs; - } - if (ret) + cs = drv->cs + i; + if ((cs->flags & VALID_ID) && cs->myid == id) { + ret = cs; break; + } } spin_unlock(&drv->lock); if (ret) @@ -983,10 +986,9 @@ void gigaset_debugdrivers(void) spin_lock(&drv->lock); for (i = 0; i < drv->minors; ++i) { gig_dbg(DEBUG_DRIVER, " index %u", i); - gig_dbg(DEBUG_DRIVER, " flags 0x%02x", - drv->flags[i]); cs = drv->cs + i; gig_dbg(DEBUG_DRIVER, " cardstate %p", cs); + gig_dbg(DEBUG_DRIVER, " flags 0x%02x", cs->flags); gig_dbg(DEBUG_DRIVER, " minor_index %u", cs->minor_index); gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver); @@ -1010,7 +1012,7 @@ static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) continue; index = minor - drv->minor; spin_lock(&drv->lock); - if (drv->flags[index] & VALID_MINOR) + if (drv->cs[index].flags & VALID_MINOR) ret = drv->cs + index; spin_unlock(&drv->lock); if (ret) @@ -1038,7 +1040,6 @@ void gigaset_freedriver(struct gigaset_driver *drv) gigaset_if_freedriver(drv); kfree(drv->cs); - kfree(drv->flags); kfree(drv); } EXPORT_SYMBOL_GPL(gigaset_freedriver); @@ -1080,12 +1081,8 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, if (!drv->cs) goto error; - drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); - if (!drv->flags) - goto error; - for (i = 0; i < minors; ++i) { - drv->flags[i] = 0; + drv->cs[i].flags = 0; drv->cs[i].driver = drv; drv->cs[i].ops = drv->ops; drv->cs[i].minor_index = i; @@ -1106,53 +1103,9 @@ error: } EXPORT_SYMBOL_GPL(gigaset_initdriver); -/* For drivers without fixed assignment device<->cardstate (usb) */ -struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv) -{ - unsigned long flags; - struct cardstate *cs = NULL; - unsigned i; - - spin_lock_irqsave(&drv->lock, flags); - if (drv->blocked) - goto exit; - for (i = 0; i < drv->minors; ++i) { - if ((drv->flags[i] & VALID_MINOR) && - !(drv->flags[i] & ASSIGNED)) { - drv->flags[i] |= ASSIGNED; - cs = drv->cs + i; - break; - } - } -exit: - spin_unlock_irqrestore(&drv->lock, flags); - return cs; -} -EXPORT_SYMBOL_GPL(gigaset_getunassignedcs); - -void gigaset_unassign(struct cardstate *cs) -{ - unsigned long flags; - unsigned *minor_flags; - struct gigaset_driver *drv; - - if (!cs) - return; - drv = cs->driver; - spin_lock_irqsave(&drv->lock, flags); - minor_flags = drv->flags + cs->minor_index; - if (*minor_flags & VALID_MINOR) - *minor_flags &= ~ASSIGNED; - spin_unlock_irqrestore(&drv->lock, flags); -} -EXPORT_SYMBOL_GPL(gigaset_unassign); - void gigaset_blockdriver(struct gigaset_driver *drv) { - unsigned long flags; - spin_lock_irqsave(&drv->lock, flags); drv->blocked = 1; - spin_unlock_irqrestore(&drv->lock, flags); } EXPORT_SYMBOL_GPL(gigaset_blockdriver); diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index cec1ef342fc..5cbf64d850e 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -735,7 +735,7 @@ static void disconnect(struct at_state_t **at_state_p) /* revert to selected idle mode */ if (!cs->cidmode) { cs->at_state.pending_commands |= PC_UMMODE; - atomic_set(&cs->commands_pending, 1); //FIXME + cs->commands_pending = 1; gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); } spin_unlock_irqrestore(&cs->lock, flags); @@ -793,15 +793,15 @@ static void init_failed(struct cardstate *cs, int mode) struct at_state_t *at_state; cs->at_state.pending_commands &= ~PC_INIT; - atomic_set(&cs->mode, mode); - atomic_set(&cs->mstate, MS_UNINITIALIZED); + cs->mode = mode; + cs->mstate = MS_UNINITIALIZED; gigaset_free_channels(cs); for (i = 0; i < cs->channels; ++i) { at_state = &cs->bcs[i].at_state; if (at_state->pending_commands & PC_CID) { at_state->pending_commands &= ~PC_CID; at_state->pending_commands |= PC_NOCID; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; } } } @@ -812,11 +812,11 @@ static void schedule_init(struct cardstate *cs, int state) gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); return; } - atomic_set(&cs->mstate, state); - atomic_set(&cs->mode, M_UNKNOWN); + cs->mstate = state; + cs->mode = M_UNKNOWN; gigaset_block_channels(cs); cs->at_state.pending_commands |= PC_INIT; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); } @@ -953,13 +953,13 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind at_state->pending_commands |= PC_CID; gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; return; error: at_state->pending_commands |= PC_NOCID; gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; return; } @@ -973,12 +973,12 @@ static void start_accept(struct at_state_t *at_state) if (retval == 0) { at_state->pending_commands |= PC_ACCEPT; gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; } else { - //FIXME + /* error reset */ at_state->pending_commands |= PC_HUP; gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; } } @@ -986,7 +986,7 @@ static void do_start(struct cardstate *cs) { gigaset_free_channels(cs); - if (atomic_read(&cs->mstate) != MS_LOCKED) + if (cs->mstate != MS_LOCKED) schedule_init(cs, MS_INIT); cs->isdn_up = 1; @@ -1000,9 +1000,9 @@ static void do_start(struct cardstate *cs) static void finish_shutdown(struct cardstate *cs) { - if (atomic_read(&cs->mstate) != MS_LOCKED) { - atomic_set(&cs->mstate, MS_UNINITIALIZED); - atomic_set(&cs->mode, M_UNKNOWN); + if (cs->mstate != MS_LOCKED) { + cs->mstate = MS_UNINITIALIZED; + cs->mode = M_UNKNOWN; } /* Tell the LL that the device is not available .. */ @@ -1022,10 +1022,10 @@ static void do_shutdown(struct cardstate *cs) { gigaset_block_channels(cs); - if (atomic_read(&cs->mstate) == MS_READY) { - atomic_set(&cs->mstate, MS_SHUTDOWN); + if (cs->mstate == MS_READY) { + cs->mstate = MS_SHUTDOWN; cs->at_state.pending_commands |= PC_SHUTDOWN; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); } else finish_shutdown(cs); @@ -1120,7 +1120,7 @@ static void handle_icall(struct cardstate *cs, struct bc_state *bcs, * In fact it doesn't. */ at_state->pending_commands |= PC_HUP; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; break; } } @@ -1130,7 +1130,7 @@ static int do_lock(struct cardstate *cs) int mode; int i; - switch (atomic_read(&cs->mstate)) { + switch (cs->mstate) { case MS_UNINITIALIZED: case MS_READY: if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) || @@ -1152,20 +1152,20 @@ static int do_lock(struct cardstate *cs) return -EBUSY; } - mode = atomic_read(&cs->mode); - atomic_set(&cs->mstate, MS_LOCKED); - atomic_set(&cs->mode, M_UNKNOWN); + mode = cs->mode; + cs->mstate = MS_LOCKED; + cs->mode = M_UNKNOWN; return mode; } static int do_unlock(struct cardstate *cs) { - if (atomic_read(&cs->mstate) != MS_LOCKED) + if (cs->mstate != MS_LOCKED) return -EINVAL; - atomic_set(&cs->mstate, MS_UNINITIALIZED); - atomic_set(&cs->mode, M_UNKNOWN); + cs->mstate = MS_UNINITIALIZED; + cs->mode = M_UNKNOWN; gigaset_free_channels(cs); if (cs->connected) schedule_init(cs, MS_INIT); @@ -1198,17 +1198,17 @@ static void do_action(int action, struct cardstate *cs, case ACT_INIT: cs->at_state.pending_commands &= ~PC_INIT; cs->cur_at_seq = SEQ_NONE; - atomic_set(&cs->mode, M_UNIMODEM); + cs->mode = M_UNIMODEM; spin_lock_irqsave(&cs->lock, flags); if (!cs->cidmode) { spin_unlock_irqrestore(&cs->lock, flags); gigaset_free_channels(cs); - atomic_set(&cs->mstate, MS_READY); + cs->mstate = MS_READY; break; } spin_unlock_irqrestore(&cs->lock, flags); cs->at_state.pending_commands |= PC_CIDMODE; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); break; case ACT_FAILINIT: @@ -1234,22 +1234,20 @@ static void do_action(int action, struct cardstate *cs, | INS_command; break; case ACT_CMODESET: - if (atomic_read(&cs->mstate) == MS_INIT || - atomic_read(&cs->mstate) == MS_RECOVER) { + if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { gigaset_free_channels(cs); - atomic_set(&cs->mstate, MS_READY); + cs->mstate = MS_READY; } - atomic_set(&cs->mode, M_CID); + cs->mode = M_CID; cs->cur_at_seq = SEQ_NONE; break; case ACT_UMODESET: - atomic_set(&cs->mode, M_UNIMODEM); + cs->mode = M_UNIMODEM; cs->cur_at_seq = SEQ_NONE; break; case ACT_FAILCMODE: cs->cur_at_seq = SEQ_NONE; - if (atomic_read(&cs->mstate) == MS_INIT || - atomic_read(&cs->mstate) == MS_RECOVER) { + if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { init_failed(cs, M_UNKNOWN); break; } @@ -1307,7 +1305,7 @@ static void do_action(int action, struct cardstate *cs, case ACT_CONNECT: if (cs->onechannel) { at_state->pending_commands |= PC_DLE1; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; break; } bcs->chstate |= CHS_D_UP; @@ -1333,7 +1331,7 @@ static void do_action(int action, struct cardstate *cs, * DLE only used for M10x with one B channel. */ at_state->pending_commands |= PC_DLE0; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; } else disconnect(p_at_state); break; @@ -1369,7 +1367,7 @@ static void do_action(int action, struct cardstate *cs, "Could not enter DLE mode. Trying to hang up.\n"); channel = cs->curchannel; cs->bcs[channel].at_state.pending_commands |= PC_HUP; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; break; case ACT_CID: /* got cid; start dialing */ @@ -1379,7 +1377,7 @@ static void do_action(int action, struct cardstate *cs, cs->bcs[channel].at_state.cid = ev->parameter; cs->bcs[channel].at_state.pending_commands |= PC_DIAL; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; break; } /* fall through */ @@ -1411,14 +1409,14 @@ static void do_action(int action, struct cardstate *cs, case ACT_ABORTDIAL: /* error/timeout during dial preparation */ cs->cur_at_seq = SEQ_NONE; at_state->pending_commands |= PC_HUP; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; break; case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */ case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */ case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */ at_state->pending_commands |= PC_HUP; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; break; case ACT_GETSTRING: /* warning: RING, ZDLE, ... are not handled properly anymore */ @@ -1515,7 +1513,7 @@ static void do_action(int action, struct cardstate *cs, break; case ACT_HUP: at_state->pending_commands |= PC_HUP; - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); break; @@ -1558,7 +1556,7 @@ static void do_action(int action, struct cardstate *cs, cs->at_state.pending_commands |= PC_UMMODE; gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); } - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; } spin_unlock_irqrestore(&cs->lock, flags); cs->waiting = 0; @@ -1741,7 +1739,7 @@ static void process_command_flags(struct cardstate *cs) int sequence; unsigned long flags; - atomic_set(&cs->commands_pending, 0); + cs->commands_pending = 0; if (cs->cur_at_seq) { gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); @@ -1779,7 +1777,7 @@ static void process_command_flags(struct cardstate *cs) ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); if (at_state->cid > 0) at_state->pending_commands |= PC_HUP; - if (atomic_read(&cs->mstate) == MS_RECOVER) { + if (cs->mstate == MS_RECOVER) { if (at_state->pending_commands & PC_CID) { at_state->pending_commands |= PC_NOCID; at_state->pending_commands &= ~PC_CID; @@ -1793,7 +1791,7 @@ static void process_command_flags(struct cardstate *cs) if (cs->at_state.pending_commands == PC_UMMODE && !cs->cidmode && list_empty(&cs->temp_at_states) - && atomic_read(&cs->mode) == M_CID) { + && cs->mode == M_CID) { sequence = SEQ_UMMODE; at_state = &cs->at_state; for (i = 0; i < cs->channels; ++i) { @@ -1860,7 +1858,7 @@ static void process_command_flags(struct cardstate *cs) } if (cs->at_state.pending_commands & PC_CIDMODE) { cs->at_state.pending_commands &= ~PC_CIDMODE; - if (atomic_read(&cs->mode) == M_UNIMODEM) { + if (cs->mode == M_UNIMODEM) { cs->retry_count = 1; schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); return; @@ -1886,11 +1884,11 @@ static void process_command_flags(struct cardstate *cs) return; } if (bcs->at_state.pending_commands & PC_CID) { - switch (atomic_read(&cs->mode)) { + switch (cs->mode) { case M_UNIMODEM: cs->at_state.pending_commands |= PC_CIDMODE; gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); - atomic_set(&cs->commands_pending, 1); + cs->commands_pending = 1; return; #ifdef GIG_MAYINITONDIAL case M_UNKNOWN: @@ -1926,7 +1924,7 @@ static void process_events(struct cardstate *cs) for (i = 0; i < 2 * MAX_EVENTS; ++i) { tail = cs->ev_tail; if (tail == head) { - if (!check_flags && !atomic_read(&cs->commands_pending)) + if (!check_flags && !cs->commands_pending) break; check_flags = 0; spin_unlock_irqrestore(&cs->ev_lock, flags); @@ -1934,7 +1932,7 @@ static void process_events(struct cardstate *cs) spin_lock_irqsave(&cs->ev_lock, flags); tail = cs->ev_tail; if (tail == head) { - if (!atomic_read(&cs->commands_pending)) + if (!cs->commands_pending) break; continue; } @@ -1971,7 +1969,7 @@ void gigaset_handle_event(unsigned long data) struct cardstate *cs = (struct cardstate *) data; /* handle incoming data on control/common channel */ - if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) { + if (cs->inbuf->head != cs->inbuf->tail) { gig_dbg(DEBUG_INTR, "processing new data"); cs->ops->handle_input(cs->inbuf); } diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 02bdaf22d7e..f365993161f 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -70,22 +70,13 @@ extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ -/* any combination of these can be given with the 'debug=' parameter to insmod, - * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and - * DEBUG_INTR. - */ +/* debug flags, combine by adding/bitwise OR */ enum debuglevel { - DEBUG_REG = 0x0002, /* serial port I/O register operations */ - DEBUG_OPEN = 0x0004, /* open/close serial port */ - DEBUG_INTR = 0x0008, /* interrupt processing */ - DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on - interrupt requests, not available as - run-time option */ + DEBUG_INTR = 0x00008, /* interrupt processing */ DEBUG_CMD = 0x00020, /* sent/received LL commands */ DEBUG_STREAM = 0x00040, /* application data stream I/O events */ DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ DEBUG_LLDATA = 0x00100, /* sent/received LL data */ - DEBUG_INTR_0 = 0x00200, /* serial port interrupt processing */ DEBUG_DRIVER = 0x00400, /* driver structure */ DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ DEBUG_WRITE = 0x01000, /* M105 data write */ @@ -93,7 +84,7 @@ enum debuglevel { DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data structures */ - DEBUG_LOCK = 0x10000, /* semaphore operations */ + DEBUG_SUSPEND = 0x10000, /* suspend/resume processing */ DEBUG_OUTPUT = 0x20000, /* output to device */ DEBUG_ISO = 0x40000, /* isochronous transfers */ DEBUG_IF = 0x80000, /* character device operations */ @@ -191,6 +182,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define HD_OPEN_ATCHANNEL (0x28) // 3070 #define HD_CLOSE_ATCHANNEL (0x29) // 3070 +/* number of B channels supported by base driver */ +#define BAS_CHANNELS 2 + /* USB frames for isochronous transfer */ #define BAS_FRAMETIME 1 /* number of milliseconds between frames */ #define BAS_NUMFRAMES 8 /* number of frames per URB */ @@ -313,7 +307,7 @@ struct inbuf_t { struct bc_state *bcs; struct cardstate *cs; int inputstate; - atomic_t head, tail; + int head, tail; unsigned char data[RBUFSIZE]; }; @@ -335,9 +329,9 @@ struct inbuf_t { * are also filled with that value */ struct isowbuf_t { - atomic_t read; - atomic_t nextread; - atomic_t write; + int read; + int nextread; + int write; atomic_t writesem; int wbits; unsigned char data[BAS_OUTBUFSIZE + BAS_OUTBUFPAD]; @@ -350,11 +344,13 @@ struct isowbuf_t { * - urb: pointer to the URB itself * - bcs: pointer to the B Channel control structure * - limit: end of write buffer area covered by this URB + * - status: URB completion status */ struct isow_urbctx_t { struct urb *urb; struct bc_state *bcs; int limit; + int status; }; /* AT state structure @@ -439,14 +435,15 @@ struct cardstate { unsigned minor_index; struct device *dev; struct device *tty_dev; + unsigned flags; const struct gigaset_ops *ops; /* Stuff to handle communication */ wait_queue_head_t waitqueue; int waiting; - atomic_t mode; /* see M_XXXX */ - atomic_t mstate; /* Modem state: see MS_XXXX */ + int mode; /* see M_XXXX */ + int mstate; /* Modem state: see MS_XXXX */ /* only changed by the event layer */ int cmd_result; @@ -503,7 +500,7 @@ struct cardstate { processed */ int curchannel; /* channel those commands are meant for */ - atomic_t commands_pending; /* flag(s) in xxx.commands_pending have + int commands_pending; /* flag(s) in xxx.commands_pending have been set */ struct tasklet_struct event_tasklet; /* tasklet for serializing AT commands. @@ -543,7 +540,6 @@ struct gigaset_driver { unsigned minor; unsigned minors; struct cardstate *cs; - unsigned *flags; int blocked; const struct gigaset_ops *ops; @@ -559,7 +555,7 @@ struct cmdbuf_t { struct bas_bc_state { /* isochronous output state */ - atomic_t running; + int running; atomic_t corrbytes; spinlock_t isooutlock; struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; @@ -574,6 +570,7 @@ struct bas_bc_state { struct urb *isoinurbs[BAS_INURBS]; unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; struct urb *isoindone; /* completed isoc read URB */ + int isoinstatus; /* status of completed URB */ int loststatus; /* status of dropped URB */ unsigned isoinlost; /* number of bytes lost */ /* state of bit unstuffing algorithm @@ -770,10 +767,6 @@ void gigaset_freedriver(struct gigaset_driver *drv); void gigaset_debugdrivers(void); struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); struct cardstate *gigaset_get_cs_by_id(int id); - -/* For drivers without fixed assignment device<->cardstate (usb) */ -struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv); -void gigaset_unassign(struct cardstate *cs); void gigaset_blockdriver(struct gigaset_driver *drv); /* Allocate and initialize card state. Calls hardware dependent @@ -792,7 +785,7 @@ int gigaset_start(struct cardstate *cs); void gigaset_stop(struct cardstate *cs); /* Tell common.c that the driver is being unloaded. */ -void gigaset_shutdown(struct cardstate *cs); +int gigaset_shutdown(struct cardstate *cs); /* Tell common.c that an skb has been sent. */ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index eb50f3dab5f..af195b07c19 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -28,12 +28,11 @@ static int if_lock(struct cardstate *cs, int *arg) return -EINVAL; if (cmd < 0) { - *arg = atomic_read(&cs->mstate) == MS_LOCKED; //FIXME remove? + *arg = cs->mstate == MS_LOCKED; return 0; } - if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED - && cs->connected) { + if (!cmd && cs->mstate == MS_LOCKED && cs->connected) { cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); cs->ops->baud_rate(cs, B115200); cs->ops->set_line_ctrl(cs, CS8); @@ -104,7 +103,7 @@ static int if_config(struct cardstate *cs, int *arg) if (*arg != 1) return -EINVAL; - if (atomic_read(&cs->mstate) != MS_LOCKED) + if (cs->mstate != MS_LOCKED) return -EBUSY; if (!cs->connected) { @@ -162,7 +161,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) tty->driver_data = NULL; cs = gigaset_get_cs_by_tty(tty); - if (!cs) + if (!cs || !try_module_get(cs->driver->owner)) return -ENODEV; if (mutex_lock_interruptible(&cs->mutex)) @@ -208,6 +207,8 @@ static void if_close(struct tty_struct *tty, struct file *filp) } mutex_unlock(&cs->mutex); + + module_put(cs->driver->owner); } static int if_ioctl(struct tty_struct *tty, struct file *file, @@ -364,7 +365,7 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) if (!cs->open_count) warn("%s: device not opened", __func__); - else if (atomic_read(&cs->mstate) != MS_LOCKED) { + else if (cs->mstate != MS_LOCKED) { warn("can't write to unlocked device"); retval = -EBUSY; } else if (!cs->connected) { @@ -398,9 +399,9 @@ static int if_write_room(struct tty_struct *tty) if (!cs->open_count) warn("%s: device not opened", __func__); - else if (atomic_read(&cs->mstate) != MS_LOCKED) { + else if (cs->mstate != MS_LOCKED) { warn("can't write to unlocked device"); - retval = -EBUSY; //FIXME + retval = -EBUSY; } else if (!cs->connected) { gig_dbg(DEBUG_ANY, "can't write to unplugged device"); retval = -EBUSY; //FIXME @@ -430,7 +431,7 @@ static int if_chars_in_buffer(struct tty_struct *tty) if (!cs->open_count) warn("%s: device not opened", __func__); - else if (atomic_read(&cs->mstate) != MS_LOCKED) { + else if (cs->mstate != MS_LOCKED) { warn("can't write to unlocked device"); retval = -EBUSY; } else if (!cs->connected) { diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index e0505f23880..e30a7773f93 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -23,9 +23,9 @@ */ void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle) { - atomic_set(&iwb->read, 0); - atomic_set(&iwb->nextread, 0); - atomic_set(&iwb->write, 0); + iwb->read = 0; + iwb->nextread = 0; + iwb->write = 0; atomic_set(&iwb->writesem, 1); iwb->wbits = 0; iwb->idle = idle; @@ -39,8 +39,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) { int read, write, freebytes; - read = atomic_read(&iwb->read); - write = atomic_read(&iwb->write); + read = iwb->read; + write = iwb->write; if ((freebytes = read - write) > 0) { /* no wraparound: need padding space within regular area */ return freebytes - BAS_OUTBUFPAD; @@ -62,7 +62,7 @@ static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b) int read; if (a == b) return 0; - read = atomic_read(&iwb->read); + read = iwb->read; if (a < b) { if (a < read && read <= b) return +1; @@ -91,18 +91,18 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb) #ifdef CONFIG_GIGASET_DEBUG gig_dbg(DEBUG_ISO, "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", - __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits); + __func__, iwb->data[iwb->write], iwb->wbits); #endif return 1; } /* finish writing - * release the write semaphore and update the maximum buffer fill level + * release the write semaphore * returns the current write position */ static inline int isowbuf_donewrite(struct isowbuf_t *iwb) { - int write = atomic_read(&iwb->write); + int write = iwb->write; atomic_inc(&iwb->writesem); return write; } @@ -116,7 +116,7 @@ static inline int isowbuf_donewrite(struct isowbuf_t *iwb) */ static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) { - int write = atomic_read(&iwb->write); + int write = iwb->write; data <<= iwb->wbits; data |= iwb->data[write]; nbits += iwb->wbits; @@ -128,7 +128,7 @@ static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) } iwb->wbits = nbits; iwb->data[write] = data & 0xff; - atomic_set(&iwb->write, write); + iwb->write = write; } /* put final flag on HDLC bitstream @@ -142,7 +142,7 @@ static inline void isowbuf_putflag(struct isowbuf_t *iwb) /* add two flags, thus reliably covering one byte */ isowbuf_putbits(iwb, 0x7e7e, 8); /* recover the idle flag byte */ - write = atomic_read(&iwb->write); + write = iwb->write; iwb->idle = iwb->data[write]; gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); /* mask extraneous bits in buffer */ @@ -160,8 +160,8 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) int read, write, limit, src, dst; unsigned char pbyte; - read = atomic_read(&iwb->nextread); - write = atomic_read(&iwb->write); + read = iwb->nextread; + write = iwb->write; if (likely(read == write)) { /* return idle frame */ return read < BAS_OUTBUFPAD ? @@ -176,7 +176,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) err("invalid size %d", size); return -EINVAL; } - src = atomic_read(&iwb->read); + src = iwb->read; if (unlikely(limit > BAS_OUTBUFSIZE + BAS_OUTBUFPAD || (read < src && limit >= src))) { err("isoc write buffer frame reservation violated"); @@ -191,7 +191,8 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) if (!isowbuf_startwrite(iwb)) return -EBUSY; /* write position could have changed */ - if (limit >= (write = atomic_read(&iwb->write))) { + write = iwb->write; + if (limit >= write) { pbyte = iwb->data[write]; /* save partial byte */ limit = write + BAS_OUTBUFPAD; @@ -213,7 +214,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) __func__, pbyte, limit); iwb->data[limit] = pbyte; /* restore partial byte */ - atomic_set(&iwb->write, limit); + iwb->write = limit; } isowbuf_donewrite(iwb); } @@ -233,7 +234,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) limit = src; } } - atomic_set(&iwb->nextread, limit); + iwb->nextread = limit; return read; } @@ -477,7 +478,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, unsigned char c; if (unlikely(count <= 0)) - return atomic_read(&iwb->write); /* better ideas? */ + return iwb->write; if (isowbuf_freebytes(iwb) < count || !isowbuf_startwrite(iwb)) { @@ -486,13 +487,13 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, } gig_dbg(DEBUG_STREAM, "put %d bytes", count); - write = atomic_read(&iwb->write); + write = iwb->write; do { c = bitrev8(*in++); iwb->data[write++] = c; write %= BAS_OUTBUFSIZE; } while (--count > 0); - atomic_set(&iwb->write, write); + iwb->write = write; iwb->idle = c; return isowbuf_donewrite(iwb); @@ -947,8 +948,8 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) unsigned tail, head, numbytes; unsigned char *src; - head = atomic_read(&inbuf->head); - while (head != (tail = atomic_read(&inbuf->tail))) { + head = inbuf->head; + while (head != (tail = inbuf->tail)) { gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); if (head > tail) tail = RBUFSIZE; @@ -956,7 +957,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) numbytes = tail - head; gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); - if (atomic_read(&cs->mstate) == MS_LOCKED) { + if (cs->mstate == MS_LOCKED) { gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src); gigaset_if_receive(inbuf->cs, src, numbytes); @@ -970,7 +971,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) if (head == RBUFSIZE) head = 0; gig_dbg(DEBUG_INTR, "setting head to %u", head); - atomic_set(&inbuf->head, head); + inbuf->head = head; } } diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index ea44302e6e7..fceeb1d5768 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -17,6 +17,7 @@ #include <linux/platform_device.h> #include <linux/tty.h> #include <linux/poll.h> +#include <linux/completion.h> /* Version Information */ #define DRIVER_AUTHOR "Tilman Schmidt" @@ -48,7 +49,7 @@ struct ser_cardstate { struct platform_device dev; struct tty_struct *tty; atomic_t refcnt; - struct mutex dead_mutex; + struct completion dead_cmp; }; static struct platform_driver device_driver = { @@ -240,7 +241,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, struct cmdbuf_t *cb; unsigned long flags; - gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? + gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? DEBUG_TRANSCMD : DEBUG_LOCKCMD, "CMD Transmit", len, buf); @@ -498,7 +499,7 @@ static struct cardstate *cs_get(struct tty_struct *tty) static void cs_put(struct cardstate *cs) { if (atomic_dec_and_test(&cs->hw.ser->refcnt)) - mutex_unlock(&cs->hw.ser->dead_mutex); + complete(&cs->hw.ser->dead_cmp); } /* @@ -527,8 +528,8 @@ gigaset_tty_open(struct tty_struct *tty) cs->dev = &cs->hw.ser->dev.dev; cs->hw.ser->tty = tty; - mutex_init(&cs->hw.ser->dead_mutex); atomic_set(&cs->hw.ser->refcnt, 1); + init_completion(&cs->hw.ser->dead_cmp); tty->disc_data = cs; @@ -536,14 +537,13 @@ gigaset_tty_open(struct tty_struct *tty) * startup system and notify the LL that we are ready to run */ if (startmode == SM_LOCKED) - atomic_set(&cs->mstate, MS_LOCKED); + cs->mstate = MS_LOCKED; if (!gigaset_start(cs)) { tasklet_kill(&cs->write_tasklet); goto error; } gig_dbg(DEBUG_INIT, "Startup of HLL done"); - mutex_lock(&cs->hw.ser->dead_mutex); return 0; error: @@ -577,7 +577,7 @@ gigaset_tty_close(struct tty_struct *tty) else { /* wait for running methods to finish */ if (!atomic_dec_and_test(&cs->hw.ser->refcnt)) - mutex_lock(&cs->hw.ser->dead_mutex); + wait_for_completion(&cs->hw.ser->dead_cmp); } /* stop operations */ @@ -714,8 +714,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, return; } - tail = atomic_read(&inbuf->tail); - head = atomic_read(&inbuf->head); + tail = inbuf->tail; + head = inbuf->head; gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes", head, tail, count); @@ -742,7 +742,7 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, } gig_dbg(DEBUG_INTR, "setting tail to %u", tail); - atomic_set(&inbuf->tail, tail); + inbuf->tail = tail; /* Everything was received .. Push data into handler */ gig_dbg(DEBUG_INTR, "%s-->BH", __func__); diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index ca4bee173cf..77d20ab0cd4 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -104,12 +104,17 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); * flags per packet. */ +/* functions called if a device of this driver is connected/disconnected */ static int gigaset_probe(struct usb_interface *interface, const struct usb_device_id *id); static void gigaset_disconnect(struct usb_interface *interface); +/* functions called before/after suspend */ +static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); +static int gigaset_resume(struct usb_interface *intf); +static int gigaset_pre_reset(struct usb_interface *intf); + static struct gigaset_driver *driver = NULL; -static struct cardstate *cardstate = NULL; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { @@ -117,12 +122,17 @@ static struct usb_driver gigaset_usb_driver = { .probe = gigaset_probe, .disconnect = gigaset_disconnect, .id_table = gigaset_table, + .suspend = gigaset_suspend, + .resume = gigaset_resume, + .reset_resume = gigaset_resume, + .pre_reset = gigaset_pre_reset, + .post_reset = gigaset_resume, }; struct usb_cardstate { struct usb_device *udev; /* usb device pointer */ struct usb_interface *interface; /* interface for this device */ - atomic_t busy; /* bulk output in progress */ + int busy; /* bulk output in progress */ /* Output buffer */ unsigned char *bulk_out_buffer; @@ -314,7 +324,7 @@ static void gigaset_modem_fill(unsigned long data) gig_dbg(DEBUG_OUTPUT, "modem_fill"); - if (atomic_read(&cs->hw.usb->busy)) { + if (cs->hw.usb->busy) { gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); return; } @@ -361,18 +371,13 @@ static void gigaset_read_int_callback(struct urb *urb) { struct inbuf_t *inbuf = urb->context; struct cardstate *cs = inbuf->cs; - int resubmit = 0; + int status = urb->status; int r; unsigned numbytes; unsigned char *src; unsigned long flags; - if (!urb->status) { - if (!cs->connected) { - err("%s: disconnected", __func__); /* should never happen */ - return; - } - + if (!status) { numbytes = urb->actual_length; if (numbytes) { @@ -389,28 +394,26 @@ static void gigaset_read_int_callback(struct urb *urb) } } else gig_dbg(DEBUG_INTR, "Received zero block length"); - resubmit = 1; } else { /* 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 (!cs->connected) { - err("%s: disconnected", __func__); /* should never happen */ - return; - } - resubmit = 1; - } + gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d", + __func__, status); + if (status == -ENOENT || status == -ESHUTDOWN) + /* killed or endpoint shutdown: don't resubmit */ + return; } - if (resubmit) { - spin_lock_irqsave(&cs->lock, flags); - r = cs->connected ? usb_submit_urb(urb, GFP_ATOMIC) : -ENODEV; + /* resubmit URB */ + spin_lock_irqsave(&cs->lock, flags); + if (!cs->connected) { spin_unlock_irqrestore(&cs->lock, flags); - if (r) - dev_err(cs->dev, "error %d when resubmitting urb.\n", - -r); + err("%s: disconnected", __func__); + return; } + r = usb_submit_urb(urb, GFP_ATOMIC); + spin_unlock_irqrestore(&cs->lock, flags); + if (r) + dev_err(cs->dev, "error %d resubmitting URB\n", -r); } @@ -418,19 +421,28 @@ static void gigaset_read_int_callback(struct urb *urb) static void gigaset_write_bulk_callback(struct urb *urb) { struct cardstate *cs = urb->context; + int status = urb->status; unsigned long flags; - if (urb->status) + switch (status) { + case 0: /* normal completion */ + break; + case -ENOENT: /* killed */ + gig_dbg(DEBUG_ANY, "%s: killed", __func__); + cs->hw.usb->busy = 0; + return; + default: dev_err(cs->dev, "bulk transfer failed (status %d)\n", - -urb->status); + -status); /* That's all we can do. Communication problems are handled by timeouts or network protocols. */ + } spin_lock_irqsave(&cs->lock, flags); if (!cs->connected) { err("%s: not connected", __func__); } else { - atomic_set(&cs->hw.usb->busy, 0); + cs->hw.usb->busy = 0; tasklet_schedule(&cs->write_tasklet); } spin_unlock_irqrestore(&cs->lock, flags); @@ -478,14 +490,14 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) cb->offset += count; cb->len -= count; - atomic_set(&ucs->busy, 1); + ucs->busy = 1; spin_lock_irqsave(&cs->lock, flags); status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; spin_unlock_irqrestore(&cs->lock, flags); if (status) { - atomic_set(&ucs->busy, 0); + ucs->busy = 0; err("could not submit urb (error %d)\n", -status); cb->len = 0; /* skip urb => remove cb+wakeup @@ -504,7 +516,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, struct cmdbuf_t *cb; unsigned long flags; - gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? + gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? DEBUG_TRANSCMD : DEBUG_LOCKCMD, "CMD Transmit", len, buf); @@ -641,7 +653,7 @@ static int write_modem(struct cardstate *cs) count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); skb_pull(bcs->tx_skb, count); - atomic_set(&ucs->busy, 1); + ucs->busy = 1; gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); spin_lock_irqsave(&cs->lock, flags); @@ -659,7 +671,7 @@ static int write_modem(struct cardstate *cs) if (ret) { err("could not submit urb (error %d)\n", -ret); - atomic_set(&ucs->busy, 0); + ucs->busy = 0; } if (!bcs->tx_skb->len) { @@ -680,53 +692,44 @@ static int gigaset_probe(struct usb_interface *interface, { int retval; struct usb_device *udev = interface_to_usbdev(interface); - unsigned int ifnum; - struct usb_host_interface *hostif; + struct usb_host_interface *hostif = interface->cur_altsetting; struct cardstate *cs = NULL; struct usb_cardstate *ucs = NULL; struct usb_endpoint_descriptor *endpoint; int buffer_size; - int alt; - 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 + gig_dbg(DEBUG_ANY, "%s: Check if device matches ...", __func__); /* 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)) + (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) { + gig_dbg(DEBUG_ANY, "device ID (0x%x, 0x%x) not for me - skip", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); return -ENODEV; - - /* this starts to become ascii art... */ - hostif = interface->cur_altsetting; - alt = hostif->desc.bAlternateSetting; - ifnum = hostif->desc.bInterfaceNumber; // FIXME ? - - if (alt != 0 || ifnum != 0) { - dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt); + } + if (hostif->desc.bInterfaceNumber != 0) { + gig_dbg(DEBUG_ANY, "interface %d not for me - skip", + hostif->desc.bInterfaceNumber); + return -ENODEV; + } + if (hostif->desc.bAlternateSetting != 0) { + dev_notice(&udev->dev, "unsupported altsetting %d - skip", + hostif->desc.bAlternateSetting); return -ENODEV; } - - /* Reject application specific intefaces - * - */ if (hostif->desc.bInterfaceClass != 255) { - dev_info(&udev->dev, - "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n", - __func__, ifnum, hostif->desc.bInterfaceClass); + dev_notice(&udev->dev, "unsupported interface class %d - skip", + hostif->desc.bInterfaceClass); return -ENODEV; } dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); - cs = gigaset_getunassignedcs(driver); - if (!cs) { - dev_warn(&udev->dev, "no free cardstate\n"); + /* allocate memory for our device state and intialize it */ + cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); + if (!cs) return -ENODEV; - } ucs = cs->hw.usb; /* save off device structure ptrs for later use */ @@ -759,7 +762,7 @@ static int gigaset_probe(struct usb_interface *interface, endpoint = &hostif->endpoint[1].desc; - atomic_set(&ucs->busy, 0); + ucs->busy = 0; ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); if (!ucs->read_urb) { @@ -792,7 +795,7 @@ 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); + cs->mstate = MS_LOCKED; if (!gigaset_start(cs)) { tasklet_kill(&cs->write_tasklet); @@ -813,7 +816,7 @@ error: usb_put_dev(ucs->udev); ucs->udev = NULL; ucs->interface = NULL; - gigaset_unassign(cs); + gigaset_freecs(cs); return retval; } @@ -824,6 +827,9 @@ static void gigaset_disconnect(struct usb_interface *interface) cs = usb_get_intfdata(interface); ucs = cs->hw.usb; + + dev_info(cs->dev, "disconnecting Gigaset USB adapter\n"); + usb_kill_urb(ucs->read_urb); gigaset_stop(cs); @@ -831,7 +837,7 @@ static void gigaset_disconnect(struct usb_interface *interface) usb_set_intfdata(interface, NULL); tasklet_kill(&cs->write_tasklet); - usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ + usb_kill_urb(ucs->bulk_out_urb); kfree(ucs->bulk_out_buffer); usb_free_urb(ucs->bulk_out_urb); @@ -844,7 +850,53 @@ static void gigaset_disconnect(struct usb_interface *interface) ucs->interface = NULL; ucs->udev = NULL; cs->dev = NULL; - gigaset_unassign(cs); + gigaset_freecs(cs); +} + +/* gigaset_suspend + * This function is called before the USB connection is suspended or reset. + */ +static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct cardstate *cs = usb_get_intfdata(intf); + + /* stop activity */ + cs->connected = 0; /* prevent rescheduling */ + usb_kill_urb(cs->hw.usb->read_urb); + tasklet_kill(&cs->write_tasklet); + usb_kill_urb(cs->hw.usb->bulk_out_urb); + + gig_dbg(DEBUG_SUSPEND, "suspend complete"); + return 0; +} + +/* gigaset_resume + * This function is called after the USB connection has been resumed or reset. + */ +static int gigaset_resume(struct usb_interface *intf) +{ + struct cardstate *cs = usb_get_intfdata(intf); + int rc; + + /* resubmit interrupt URB */ + cs->connected = 1; + rc = usb_submit_urb(cs->hw.usb->read_urb, GFP_KERNEL); + if (rc) { + dev_err(cs->dev, "Could not submit read URB (error %d)\n", -rc); + return rc; + } + + gig_dbg(DEBUG_SUSPEND, "resume complete"); + return 0; +} + +/* gigaset_pre_reset + * This function is called before the USB connection is reset. + */ +static int gigaset_pre_reset(struct usb_interface *intf) +{ + /* same as suspend */ + return gigaset_suspend(intf, PMSG_ON); } static const struct gigaset_ops ops = { @@ -880,11 +932,6 @@ static int __init usb_gigaset_init(void) &ops, THIS_MODULE)) == NULL) goto error; - /* allocate memory for our device state and intialize it */ - cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); - if (!cardstate) - goto error; - /* register this driver with the USB subsystem */ result = usb_register(&gigaset_usb_driver); if (result < 0) { @@ -897,9 +944,7 @@ static int __init usb_gigaset_init(void) info(DRIVER_DESC); return 0; -error: if (cardstate) - gigaset_freecs(cardstate); - cardstate = NULL; +error: if (driver) gigaset_freedriver(driver); driver = NULL; @@ -913,11 +958,16 @@ error: if (cardstate) */ static void __exit usb_gigaset_exit(void) { + int i; + gigaset_blockdriver(driver); /* => probe will fail * => no gigaset_start any more */ - gigaset_shutdown(cardstate); + /* stop all connected devices */ + for (i = 0; i < driver->minors; i++) + gigaset_shutdown(driver->cs + i); + /* from now on, no isdn callback should be possible */ /* deregister this driver with the USB subsystem */ @@ -925,8 +975,6 @@ static void __exit usb_gigaset_exit(void) /* this will call the disconnect-callback */ /* from now on, no disconnect/probe callback should be running */ - gigaset_freecs(cardstate); - cardstate = NULL; gigaset_freedriver(driver); driver = NULL; } diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c index 0db9cc661e2..84318ec8d13 100644 --- a/drivers/isdn/hardware/eicon/debug.c +++ b/drivers/isdn/hardware/eicon/debug.c @@ -1188,7 +1188,7 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) { if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) && (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) { - dword rx_dma_magic; + dword uninitialized_var(rx_dma_magic); if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) { pC->xbuffer[0] = LLI; pC->xbuffer[1] = 8; diff --git a/drivers/isdn/hardware/eicon/debuglib.c b/drivers/isdn/hardware/eicon/debuglib.c index a19b7ffe9ac..e39c5c1f623 100644 --- a/drivers/isdn/hardware/eicon/debuglib.c +++ b/drivers/isdn/hardware/eicon/debuglib.c @@ -106,7 +106,7 @@ DbgRegister (char *drvName, char *drvTag, unsigned long dbgMask) return (1) ; } /* - * Check if we registered whith an old maint driver (see debuglib.h) + * Check if we registered with an old maint driver (see debuglib.h) */ if ( myDriverDebugHandle.dbg_end != NULL /* location of 'dbg_prt' in _OldDbgHandle_ struct */ diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h index 11b3b9edd1d..016410cf227 100644 --- a/drivers/isdn/hardware/eicon/debuglib.h +++ b/drivers/isdn/hardware/eicon/debuglib.h @@ -177,7 +177,7 @@ DBG_DECL(PRV3) } } #endif /* - * For event level debug use a separate define, the paramete are + * For event level debug use a separate define, the parameter are * different and cause compiler errors on some systems. */ #define DBG_EVL_ID(args) \ diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c index ce8df387890..10760b3c5eb 100644 --- a/drivers/isdn/hardware/eicon/di.c +++ b/drivers/isdn/hardware/eicon/di.c @@ -285,7 +285,7 @@ byte pr_dpc(ADAPTER * a) a->ram_in(a, &RcIn->RcId), a->ram_in(a, &RcIn->RcCh), a->ram_inw(a, &RcIn->Reference), - tmp[0], /* type of extended informtion */ + tmp[0], /* type of extended information */ tmp[1]); /* extended information */ a->ram_out(a, &RcIn->Rc, 0); } diff --git a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c index ffa2afa77c2..1403a5458e6 100644 --- a/drivers/isdn/hardware/eicon/diva.c +++ b/drivers/isdn/hardware/eicon/diva.c @@ -515,12 +515,11 @@ diva_xdi_read(void *adapter, void *os_handle, void __user *dst, irqreturn_t diva_os_irq_wrapper(int irq, void *context) { - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context; + diva_os_xdi_adapter_t *a = context; diva_xdi_clear_interrupts_proc_t clear_int_proc; - if (!a || !a->xdi_adapter.diva_isr_handler) { + if (!a || !a->xdi_adapter.diva_isr_handler) return IRQ_NONE; - } if ((clear_int_proc = a->clear_interrupts_proc)) { (*clear_int_proc) (a); diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c index ccd35d047ec..1ff98e7eb79 100644 --- a/drivers/isdn/hardware/eicon/message.c +++ b/drivers/isdn/hardware/eicon/message.c @@ -4941,7 +4941,7 @@ void sig_ind(PLCI * plci) /* b = IE1 */ /* S = IE1 length + cont. */ /* b = IE2 */ - /* S = IE2 lenght + cont. */ + /* S = IE2 length + cont. */ sendf(plci->appl, _MANUFACTURER_I, Id, @@ -9027,7 +9027,7 @@ static byte AddInfo(byte **add_i, /* facility is a nested structure */ /* FTY can be more than once */ - if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f ) + if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f)) { add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */ } diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 035d158779d..0f1db1f669b 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -263,11 +263,7 @@ hdlc_empty_fifo(struct BCState *bcs, int count) outl(idx, cs->hw.avm.cfg_reg + 4); while (cnt < count) { #ifdef __powerpc__ -#ifdef CONFIG_APUS - *ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); -#else *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); -#endif /* CONFIG_APUS */ #else *ptr++ = inl(cs->hw.avm.isac); #endif /* __powerpc__ */ @@ -328,11 +324,7 @@ hdlc_fill_fifo(struct BCState *bcs) if (cs->subtyp == AVM_FRITZ_PCI) { while (cnt<count) { #ifdef __powerpc__ -#ifdef CONFIG_APUS - out_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++); -#else out_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++); -#endif /* CONFIG_APUS */ #else outl(*ptr++, cs->hw.avm.isac); #endif /* __powerpc__ */ diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index f85450146bd..d3999a8e9f8 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -541,7 +541,7 @@ hycapi_rx_capipkt(hysdn_card * card, unsigned char *buf, unsigned short len) } ctrl = &cinfo->capi_ctrl; if(len < CAPI_MSG_BASELEN) { - printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, lenght %d!\n", + printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, length %d!\n", card->myid, len); return; } diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 9cb6e5021ad..133eb18e65c 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1917,7 +1917,6 @@ isdn_tty_modem_init(void) info->owner = THIS_MODULE; #endif spin_lock_init(&info->readlock); - init_MUTEX(&info->write_sem); sprintf(info->last_cause, "0000"); sprintf(info->last_num, "none"); info->last_dir = 0; diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c index a943d078bac..f93de4a3035 100644 --- a/drivers/isdn/i4l/isdn_ttyfax.c +++ b/drivers/isdn/i4l/isdn_ttyfax.c @@ -834,7 +834,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) char *rp = &f->resolution; p[0] += 2; - if (!info->faxonline & 1) /* not outgoing connection */ + if (!(info->faxonline & 1)) /* not outgoing connection */ PARSE_ERROR1; for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) { diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 82d957bde29..bf7997abc4a 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1302,7 +1302,7 @@ icn_command(isdn_ctrl * c, icn_card * card) } break; case ISDN_CMD_DIAL: - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; if (card->leased) break; @@ -1328,7 +1328,7 @@ icn_command(isdn_ctrl * c, icn_card * card) } break; case ISDN_CMD_ACCEPTD: - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; if (c->arg < ICN_BCH) { a = c->arg + 1; @@ -1348,7 +1348,7 @@ icn_command(isdn_ctrl * c, icn_card * card) } break; case ISDN_CMD_ACCEPTB: - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; if (c->arg < ICN_BCH) { a = c->arg + 1; @@ -1366,7 +1366,7 @@ icn_command(isdn_ctrl * c, icn_card * card) } break; case ISDN_CMD_HANGUP: - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; if (c->arg < ICN_BCH) { a = c->arg + 1; @@ -1375,7 +1375,7 @@ icn_command(isdn_ctrl * c, icn_card * card) } break; case ISDN_CMD_SETEAZ: - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; if (card->leased) break; @@ -1391,7 +1391,7 @@ icn_command(isdn_ctrl * c, icn_card * card) } break; case ISDN_CMD_CLREAZ: - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; if (card->leased) break; @@ -1405,7 +1405,7 @@ icn_command(isdn_ctrl * c, icn_card * card) } break; case ISDN_CMD_SETL2: - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; if ((c->arg & 255) < ICN_BCH) { a = c->arg; @@ -1424,7 +1424,7 @@ icn_command(isdn_ctrl * c, icn_card * card) } break; case ISDN_CMD_SETL3: - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; return 0; default: @@ -1471,7 +1471,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) icn_card *card = icn_findcard(id); if (card) { - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; return (icn_writecmd(buf, len, 1, card)); } @@ -1486,7 +1486,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel) icn_card *card = icn_findcard(id); if (card) { - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; return (icn_readstatus(buf, len, card)); } @@ -1501,7 +1501,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) icn_card *card = icn_findcard(id); if (card) { - if (!card->flags & ICN_FLAGS_RUNNING) + if (!(card->flags & ICN_FLAGS_RUNNING)) return -ENODEV; return (icn_sendbuf(channel, ack, skb, card)); } diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index bb92e3cd933..655ef9a3f4d 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -1184,7 +1184,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) } break; case ISDN_CMD_DIAL: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) + if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) return -ENODEV; if (card->leased) break; @@ -1210,7 +1210,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) } break; case ISDN_CMD_ACCEPTD: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) + if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) return -ENODEV; if (c->arg < ISDNLOOP_BCH) { a = c->arg + 1; @@ -1238,7 +1238,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) } break; case ISDN_CMD_ACCEPTB: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) + if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) return -ENODEV; if (c->arg < ISDNLOOP_BCH) { a = c->arg + 1; @@ -1264,7 +1264,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); break; case ISDN_CMD_HANGUP: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) + if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) return -ENODEV; if (c->arg < ISDNLOOP_BCH) { a = c->arg + 1; @@ -1273,7 +1273,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) } break; case ISDN_CMD_SETEAZ: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) + if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) return -ENODEV; if (card->leased) break; @@ -1303,7 +1303,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) } break; case ISDN_CMD_SETL2: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) + if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) return -ENODEV; if ((c->arg & 255) < ISDNLOOP_BCH) { a = c->arg; @@ -1395,7 +1395,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel) isdnloop_card *card = isdnloop_findcard(id); if (card) { - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) + if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) return -ENODEV; return (isdnloop_readstatus(buf, len, card)); } @@ -1410,7 +1410,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) isdnloop_card *card = isdnloop_findcard(id); if (card) { - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) + if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) return -ENODEV; /* ack request stored in skb scratch area */ *(skb->head) = ack; |