diff options
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/gigaset/Kconfig | 4 | ||||
-rw-r--r-- | drivers/isdn/gigaset/asyncdata.c | 132 | ||||
-rw-r--r-- | drivers/isdn/gigaset/bas-gigaset.c | 1321 | ||||
-rw-r--r-- | drivers/isdn/gigaset/common.c | 504 | ||||
-rw-r--r-- | drivers/isdn/gigaset/ev-layer.c | 670 | ||||
-rw-r--r-- | drivers/isdn/gigaset/gigaset.h | 601 | ||||
-rw-r--r-- | drivers/isdn/gigaset/i4l.c | 229 | ||||
-rw-r--r-- | drivers/isdn/gigaset/interface.c | 235 | ||||
-rw-r--r-- | drivers/isdn/gigaset/isocdata.c | 139 | ||||
-rw-r--r-- | drivers/isdn/gigaset/proc.c | 51 | ||||
-rw-r--r-- | drivers/isdn/gigaset/usb-gigaset.c | 455 | ||||
-rw-r--r-- | drivers/isdn/hardware/avm/avm_cs.c | 185 | ||||
-rw-r--r-- | drivers/isdn/hisax/avma1_cs.c | 182 | ||||
-rw-r--r-- | drivers/isdn/hisax/elsa_cs.c | 112 | ||||
-rw-r--r-- | drivers/isdn/hisax/sedlbauer_cs.c | 143 | ||||
-rw-r--r-- | drivers/isdn/hisax/teles_cs.c | 121 | ||||
-rw-r--r-- | drivers/isdn/i4l/isdn_ppp.c | 20 |
17 files changed, 2412 insertions, 2692 deletions
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 53c4fb6..5b203fe 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig @@ -3,8 +3,8 @@ menu "Siemens Gigaset" config ISDN_DRV_GIGASET tristate "Siemens Gigaset support (isdn)" - depends on ISDN_I4L && m -# depends on ISDN_I4L && MODULES + depends on ISDN_I4L + select CRC_CCITT help Say m here if you have a Gigaset or Sinus isdn device. diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 171f8b7..ce3cd77 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -3,7 +3,7 @@ * * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>, * Hansjoerg Lipp <hjlipp@web.de>, - * Stefan Eilers <Eilers.Stefan@epost.de>. + * Stefan Eilers. * * ===================================================================== * This program is free software; you can redistribute it and/or @@ -11,10 +11,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: asyncdata.c,v 1.2.2.7 2005/11/13 23:05:18 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -45,7 +41,7 @@ static inline int muststuff(unsigned char c) * number of processed bytes */ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) + struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; unsigned cbytes = cs->cbytes; @@ -55,10 +51,11 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, for (;;) { cs->respdata[cbytes] = c; if (c == 10 || c == 13) { - dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", - __func__, cbytes); + gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", + __func__, cbytes); cs->cbytes = cbytes; - gigaset_handle_modem_response(cs); /* can change cs->dle */ + gigaset_handle_modem_response(cs); /* can change + cs->dle */ cbytes = 0; if (cs->dle && @@ -71,7 +68,7 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, if (cbytes < MAX_RESP_SIZE - 1) cbytes++; else - warn("response too large"); + dev_warn(cs->dev, "response too large\n"); } if (!numbytes) @@ -96,11 +93,12 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, * number of processed bytes */ static inline int lock_loop(unsigned char *src, int numbytes, - struct inbuf_t *inbuf) + struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; - gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src, 0); + gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", + numbytes, src); gigaset_if_receive(cs, src, numbytes); return numbytes; @@ -115,24 +113,18 @@ static inline int lock_loop(unsigned char *src, int numbytes, * numbytes (all bytes processed) on error --FIXME */ static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) + struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; struct bc_state *bcs = inbuf->bcs; - int inputstate; - __u16 fcs; - struct sk_buff *skb; + int inputstate = bcs->inputstate; + __u16 fcs = bcs->fcs; + struct sk_buff *skb = bcs->skb; unsigned char error; struct sk_buff *compskb; int startbytes = numbytes; int l; - IFNULLRETVAL(bcs, numbytes); - inputstate = bcs->inputstate; - fcs = bcs->fcs; - skb = bcs->skb; - IFNULLRETVAL(skb, numbytes); - if (unlikely(inputstate & INS_byte_stuff)) { inputstate &= ~INS_byte_stuff; goto byte_stuff; @@ -156,39 +148,37 @@ byte_stuff: c ^= PPP_TRANS; #ifdef CONFIG_GIGASET_DEBUG if (unlikely(!muststuff(c))) - dbg(DEBUG_HDLC, - "byte stuffed: 0x%02x", c); + gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); #endif } else if (unlikely(c == PPP_FLAG)) { if (unlikely(inputstate & INS_skip_frame)) { if (!(inputstate & INS_have_data)) { /* 7E 7E */ - //dbg(DEBUG_HDLC, "(7e)7e------------------------"); #ifdef CONFIG_GIGASET_DEBUG ++bcs->emptycount; #endif } else - dbg(DEBUG_HDLC, + gig_dbg(DEBUG_HDLC, "7e----------------------------"); /* end of frame */ error = 1; gigaset_rcv_error(NULL, cs, bcs); } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ - //dbg(DEBUG_HDLC, "(7e)7e------------------------"); #ifdef CONFIG_GIGASET_DEBUG ++bcs->emptycount; #endif break; } else { - dbg(DEBUG_HDLC, - "7e----------------------------"); + gig_dbg(DEBUG_HDLC, + "7e----------------------------"); /* end of frame */ error = 0; if (unlikely(fcs != PPP_GOODFCS)) { - err("Packet checksum at %lu failed, " - "packet is corrupted (%u bytes)!", + dev_err(cs->dev, + "Packet checksum at %lu failed, " + "packet is corrupted (%u bytes)!\n", bcs->rcvbytes, skb->len); compskb = NULL; gigaset_rcv_error(compskb, cs, bcs); @@ -202,9 +192,11 @@ byte_stuff: skb = NULL; inputstate |= INS_skip_frame; if (l == 1) { - err("invalid packet size (1)!"); + dev_err(cs->dev, + "invalid packet size (1)!\n"); error = 1; - gigaset_rcv_error(NULL, cs, bcs); + gigaset_rcv_error(NULL, + cs, bcs); } } if (likely(!(error || @@ -227,7 +219,8 @@ byte_stuff: } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) { skb_reserve(skb, HW_HDR_LEN); } else { - warn("could not allocate new skb"); + dev_warn(cs->dev, + "could not allocate new skb\n"); inputstate |= INS_skip_frame; } @@ -235,7 +228,7 @@ byte_stuff: #ifdef CONFIG_GIGASET_DEBUG } else if (unlikely(muststuff(c))) { /* Should not happen. Possible after ZDLE=1<CR><LF>. */ - dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); + gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); #endif } @@ -243,8 +236,8 @@ byte_stuff: #ifdef CONFIG_GIGASET_DEBUG if (unlikely(!(inputstate & INS_have_data))) { - dbg(DEBUG_HDLC, - "7e (%d x) ================", bcs->emptycount); + gig_dbg(DEBUG_HDLC, "7e (%d x) ================", + bcs->emptycount); bcs->emptycount = 0; } #endif @@ -253,14 +246,13 @@ byte_stuff: if (likely(!(inputstate & INS_skip_frame))) { if (unlikely(skb->len == SBUFSIZE)) { - warn("received packet too long"); + dev_warn(cs->dev, "received packet too long\n"); dev_kfree_skb_any(skb); skb = NULL; inputstate |= INS_skip_frame; break; } - *gigaset_skb_put_quick(skb, 1) = c; - /* *__skb_put (skb, 1) = c; */ + *__skb_put(skb, 1) = c; fcs = crc_ccitt_byte(fcs, c); } @@ -289,19 +281,14 @@ byte_stuff: * numbytes (all bytes processed) on error --FIXME */ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) + struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; struct bc_state *bcs = inbuf->bcs; - int inputstate; - struct sk_buff *skb; + int inputstate = bcs->inputstate; + struct sk_buff *skb = bcs->skb; int startbytes = numbytes; - IFNULLRETVAL(bcs, numbytes); - inputstate = bcs->inputstate; - skb = bcs->skb; - IFNULLRETVAL(skb, numbytes); - for (;;) { /* add character */ inputstate |= INS_have_data; @@ -309,13 +296,13 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, if (likely(!(inputstate & INS_skip_frame))) { if (unlikely(skb->len == SBUFSIZE)) { //FIXME just pass skb up and allocate a new one - warn("received packet too long"); + dev_warn(cs->dev, "received packet too long\n"); dev_kfree_skb_any(skb); skb = NULL; inputstate |= INS_skip_frame; break; } - *gigaset_skb_put_quick(skb, 1) = gigaset_invtab[c]; + *__skb_put(skb, 1) = gigaset_invtab[c]; } if (unlikely(!numbytes)) @@ -343,7 +330,7 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, != NULL)) { skb_reserve(skb, HW_HDR_LEN); } else { - warn("could not allocate new skb"); + dev_warn(cs->dev, "could not allocate new skb\n"); inputstate |= INS_skip_frame; } } @@ -364,13 +351,13 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) head = atomic_read(&inbuf->head); tail = atomic_read(&inbuf->tail); - dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); + gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); if (head != tail) { cs = inbuf->cs; src = inbuf->data + head; numbytes = (head > tail ? RBUFSIZE : tail) - head; - dbg(DEBUG_INTR, "processing %u bytes", numbytes); + gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); while (numbytes) { if (atomic_read(&cs->mstate) == MS_LOCKED) { @@ -392,8 +379,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) if (!(inbuf->inputstate & INS_DLE_char)) { - /* FIXME Einfach je nach Modus Funktionszeiger in cs setzen [hier+hdlc_loop]? */ - /* FIXME Spart folgendes "if" und ermoeglicht andere Protokolle */ + /* FIXME use function pointers? */ if (inbuf->inputstate & INS_command) procbytes = cmd_loop(c, src, numbytes, inbuf); else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC) @@ -403,13 +389,14 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) src += procbytes; numbytes -= procbytes; - } else { /* DLE-char */ + } else { /* DLE char */ inbuf->inputstate &= ~INS_DLE_char; switch (c) { case 'X': /*begin of command*/ #ifdef CONFIG_GIGASET_DEBUG if (inbuf->inputstate & INS_command) - err("received <DLE> 'X' in command mode"); + dev_err(cs->dev, + "received <DLE> 'X' in command mode\n"); #endif inbuf->inputstate |= INS_command | INS_DLE_command; @@ -417,7 +404,8 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) case '.': /*end of command*/ #ifdef CONFIG_GIGASET_DEBUG if (!(inbuf->inputstate & INS_command)) - err("received <DLE> '.' in hdlc mode"); + dev_err(cs->dev, + "received <DLE> '.' in hdlc mode\n"); #endif inbuf->inputstate &= cs->dle ? ~(INS_DLE_command|INS_command) @@ -425,7 +413,9 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) break; //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */ default: - err("received 0x10 0x%02x!", (int) c); + dev_err(cs->dev, + "received 0x10 0x%02x!\n", + (int) c); /* FIXME: reset driver?? */ } } @@ -444,7 +434,7 @@ nextbyte: } } - dbg(DEBUG_INTR, "setting head to %u", head); + gig_dbg(DEBUG_INTR, "setting head to %u", head); atomic_set(&inbuf->head, head); } } @@ -479,14 +469,13 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) stuf_cnt++; fcs = crc_ccitt_byte(fcs, *cp++); } - fcs ^= 0xffff; /* complement */ + fcs ^= 0xffff; /* complement */ /* size of new buffer: original size + number of stuffing bytes * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes */ hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head); if (!hdlc_skb) { - err("unable to allocate memory for HDLC encoding!"); dev_kfree_skb(skb); return NULL; } @@ -508,7 +497,7 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) } /* Finally add FCS (byte stuffed) and flag sequence */ - c = (fcs & 0x00ff); /* least significant byte first */ + c = (fcs & 0x00ff); /* least significant byte first */ if (muststuff(c)) { *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE; c ^= PPP_TRANS; @@ -546,7 +535,6 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) /* worst case: every byte must be stuffed */ iraw_skb = dev_alloc_skb(2*skb->len + tail + head); if (!iraw_skb) { - err("unable to allocate memory for HDLC encoding!"); dev_kfree_skb(skb); return NULL; } @@ -577,21 +565,23 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) */ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) { - unsigned len; - - IFNULLRETVAL(bcs, -EFAULT); - IFNULLRETVAL(skb, -EFAULT); - len = skb->len; + unsigned len = skb->len; + unsigned long flags; if (bcs->proto2 == ISDN_PROTO_L2_HDLC) skb = HDLC_Encode(skb, HW_HDR_LEN, 0); else skb = iraw_encode(skb, HW_HDR_LEN, 0); - if (!skb) + if (!skb) { + err("unable to allocate memory for encoding!\n"); return -ENOMEM; + } skb_queue_tail(&bcs->squeue, skb); - tasklet_schedule(&bcs->cs->write_tasklet); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->cs->connected) + tasklet_schedule(&bcs->cs->write_tasklet); + spin_unlock_irqrestore(&bcs->cs->lock, flags); return len; /* ok so far */ } diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 31f0f07..eb41aba 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -3,9 +3,7 @@ * * Copyright (c) 2001 by Hansjoerg Lipp <hjlipp@web.de>, * Tilman Schmidt <tilman@imap.cc>, - * Stefan Eilers <Eilers.Stefan@epost.de>. - * - * Based on usb-gigaset.c. + * Stefan Eilers. * * ===================================================================== * This program is free software; you can redistribute it and/or @@ -13,10 +11,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: bas-gigaset.c,v 1.52.4.19 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -30,7 +24,7 @@ #include <linux/moduleparam.h> /* Version Information */ -#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>" +#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers" #define DRIVER_DESC "USB Driver for Gigaset 307x" @@ -50,19 +44,20 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); #define GIGASET_DEVFSNAME "gig/bas/" #define GIGASET_DEVNAME "ttyGB" -#define IF_WRITEBUF 256 //FIXME +/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ +#define IF_WRITEBUF 264 /* Values for the Gigaset 307x */ #define USB_GIGA_VENDOR_ID 0x0681 -#define USB_GIGA_PRODUCT_ID 0x0001 -#define USB_4175_PRODUCT_ID 0x0002 +#define USB_3070_PRODUCT_ID 0x0001 +#define USB_3075_PRODUCT_ID 0x0002 #define USB_SX303_PRODUCT_ID 0x0021 #define USB_SX353_PRODUCT_ID 0x0022 /* table of devices that work with this driver */ static struct usb_device_id gigaset_table [] = { - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_GIGA_PRODUCT_ID) }, - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_4175_PRODUCT_ID) }, + { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, + { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) }, { } /* Terminating entry */ @@ -70,9 +65,6 @@ static struct usb_device_id gigaset_table [] = { MODULE_DEVICE_TABLE(usb, gigaset_table); -/* Get a minor range for your devices from the usb maintainer */ -#define USB_SKEL_MINOR_BASE 200 - /*======================= local function prototypes =============================*/ /* This function is called if a new device is connected to the USB port. It @@ -84,29 +76,33 @@ 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); +static void read_ctrl_callback(struct urb *, struct pt_regs *); +static void stopurbs(struct bas_bc_state *); +static int atwrite_submit(struct cardstate *, unsigned char *, int); +static int start_cbsend(struct cardstate *); /*==============================================================================*/ struct bas_cardstate { - struct usb_device *udev; /* USB device pointer */ - struct usb_interface *interface; /* interface for this device */ + struct usb_device *udev; /* USB device pointer */ + struct usb_interface *interface; /* interface for this device */ unsigned char minor; /* starting minor number */ - struct urb *urb_ctrl; /* control pipe default URB */ + struct urb *urb_ctrl; /* control pipe default URB */ struct usb_ctrlrequest dr_ctrl; struct timer_list timer_ctrl; /* control request timeout */ struct timer_list timer_atrdy; /* AT command ready timeout */ - struct urb *urb_cmd_out; /* for sending AT commands */ + struct urb *urb_cmd_out; /* for sending AT commands */ struct usb_ctrlrequest dr_cmd_out; int retry_cmd_out; - struct urb *urb_cmd_in; /* for receiving AT replies */ + struct urb *urb_cmd_in; /* for receiving AT replies */ struct usb_ctrlrequest dr_cmd_in; struct timer_list timer_cmd_in; /* receive request timeout */ - unsigned char *rcvbuf; /* AT reply receive buffer */ + unsigned char *rcvbuf; /* AT reply receive buffer */ - struct urb *urb_int_in; /* URB for interrupt pipe */ + struct urb *urb_int_in; /* URB for interrupt pipe */ unsigned char int_in_buf[3]; spinlock_t lock; /* locks all following */ @@ -118,12 +114,14 @@ struct bas_cardstate { }; /* status of direct USB connection to 307x base (bits in basstate) */ -#define BS_ATOPEN 0x001 -#define BS_B1OPEN 0x002 -#define BS_B2OPEN 0x004 -#define BS_ATREADY 0x008 -#define BS_INIT 0x010 -#define BS_ATTIMER 0x020 +#define BS_ATOPEN 0x001 /* AT channel open */ +#define BS_B1OPEN 0x002 /* B channel 1 open */ +#define BS_B2OPEN 0x004 /* B channel 2 open */ +#define BS_ATREADY 0x008 /* base ready for AT command */ +#define BS_INIT 0x010 /* base has signalled INIT_OK */ +#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 */ static struct gigaset_driver *driver = NULL; @@ -137,6 +135,47 @@ static struct usb_driver gigaset_usb_driver = { .id_table = gigaset_table, }; +/* get message text for usb_submit_urb return code + */ +static char *get_usb_rcmsg(int rc) +{ + static char unkmsg[28]; + + switch (rc) { + case 0: + return "success"; + case -ENOMEM: + return "out of memory"; + case -ENODEV: + return "device not present"; + case -ENOENT: + return "endpoint not present"; + case -ENXIO: + return "URB type not supported"; + case -EINVAL: + return "invalid argument"; + case -EAGAIN: + return "start frame too early or too much scheduled"; + case -EFBIG: + return "too many isochronous frames requested"; + case -EPIPE: + return "endpoint stalled"; + case -EMSGSIZE: + return "invalid packet size"; + case -ENOSPC: + return "would overcommit USB bandwidth"; + case -ESHUTDOWN: + return "device shut down"; + case -EPERM: + return "reject flag set"; + case -EHOSTUNREACH: + return "device suspended"; + default: + snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", rc); + return unkmsg; + } +} + /* get message text for USB status code */ static char *get_usb_statmsg(int status) @@ -147,43 +186,37 @@ static char *get_usb_statmsg(int status) case 0: return "success"; case -ENOENT: - return "canceled"; - case -ECONNRESET: - return "canceled (async)"; + return "unlinked (sync)"; case -EINPROGRESS: return "pending"; case -EPROTO: - return "bit stuffing or unknown USB error"; + return "bit stuffing error, timeout, or unknown USB error"; case -EILSEQ: - return "Illegal byte sequence (CRC mismatch)"; - case -EPIPE: - return "babble detect or endpoint stalled"; - case -ENOSR: - return "buffer error"; + return "CRC mismatch, timeout, or unknown USB error"; case -ETIMEDOUT: return "timed out"; - case -ENODEV: - return "device not present"; + case -EPIPE: + return "endpoint stalled"; + case -ECOMM: + return "IN buffer overrun"; + case -ENOSR: + return "OUT buffer underrun"; + case -EOVERFLOW: + return "too much data"; case -EREMOTEIO: return "short packet detected"; + case -ENODEV: + return "device removed"; case -EXDEV: return "partial isochronous transfer"; case -EINVAL: return "invalid argument"; - case -ENXIO: - return "URB already queued"; - case -EAGAIN: - return "isochronous start frame too early or too much scheduled"; - case -EFBIG: - return "too many isochronous frames requested"; - case -EMSGSIZE: - return "endpoint message size zero"; + case -ECONNRESET: + return "unlinked (async)"; case -ESHUTDOWN: - return "endpoint shutdown"; - case -EBUSY: - return "another request pending"; + return "device shut down"; default: - snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", status); + snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status); return unkmsg; } } @@ -208,53 +241,54 @@ static inline char *usb_pipetype_str(int pipe) * write content of URB to syslog for debugging */ static inline void dump_urb(enum debuglevel level, const char *tag, - struct urb *urb) + struct urb *urb) { #ifdef CONFIG_GIGASET_DEBUG int i; - IFNULLRET(tag); - dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb); + gig_dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb); if (urb) { - dbg(level, - " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " - "status=%d, 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, - urb->transfer_flags); - dbg(level, - " transfer_buffer=0x%08lx[%d], actual_length=%d, " - "bandwidth=%d, setup_packet=0x%08lx,", - (unsigned long) urb->transfer_buffer, - urb->transfer_buffer_length, urb->actual_length, - urb->bandwidth, (unsigned long) urb->setup_packet); - dbg(level, - " start_frame=%d, number_of_packets=%d, interval=%d, " - "error_count=%d,", - urb->start_frame, urb->number_of_packets, urb->interval, - urb->error_count); - dbg(level, - " context=0x%08lx, complete=0x%08lx, iso_frame_desc[]={", - (unsigned long) urb->context, - (unsigned long) urb->complete); + gig_dbg(level, + " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " + "status=%d, 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, + urb->transfer_flags); + gig_dbg(level, + " transfer_buffer=0x%08lx[%d], actual_length=%d, " + "bandwidth=%d, setup_packet=0x%08lx,", + (unsigned long) urb->transfer_buffer, + urb->transfer_buffer_length, urb->actual_length, + urb->bandwidth, (unsigned long) urb->setup_packet); + gig_dbg(level, + " start_frame=%d, number_of_packets=%d, interval=%d, " + "error_count=%d,", + urb->start_frame, urb->number_of_packets, urb->interval, + urb->error_count); + gig_dbg(level, + " context=0x%08lx, complete=0x%08lx, " + "iso_frame_desc[]={", + (unsigned long) urb->context, + (unsigned long) urb->complete); for (i = 0; i < urb->number_of_packets; i++) { - struct usb_iso_packet_descriptor *pifd = &urb->iso_frame_desc[i]; - dbg(level, - " {offset=%u, length=%u, actual_length=%u, " - "status=%u}", - pifd->offset, pifd->length, pifd->actual_length, - pifd->status); + struct usb_iso_packet_descriptor *pifd + = &urb->iso_frame_desc[i]; + gig_dbg(level, + " {offset=%u, length=%u, actual_length=%u, " + "status=%u}", + pifd->offset, pifd->length, pifd->actual_length, + pifd->status); } } - dbg(level, "}}"); + gig_dbg(level, "}}"); #endif } /* read/set modem control bits etc. (m10x only) */ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) + unsigned new_state) { return -EINVAL; } @@ -280,43 +314,39 @@ static inline void error_hangup(struct bc_state *bcs) { struct cardstate *cs = bcs->cs; - dbg(DEBUG_ANY, - "%s: scheduling HUP for channel %d", __func__, bcs->channel); + gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d", + __func__, bcs->channel); - if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { - //FIXME what should we do? - return; - } + if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) + dev_err(cs->dev, "event queue full\n"); gigaset_schedule_event(cs); } /* error_reset * reset Gigaset device because of an unrecoverable error - * This function may be called from any context and takes care of scheduling - * the necessary actions for execution outside of interrupt context. + * This function may be called from any context, and should take care of + * scheduling the necessary actions for execution outside of interrupt context. + * Right now, it just generates a kernel message calling for help. * argument: * controller state structure */ static inline void error_reset(struct cardstate *cs) { //FIXME try to recover without bothering the user - err("unrecoverable error - please disconnect the Gigaset base to reset"); + dev_err(cs->dev, + "unrecoverable error - please disconnect Gigaset base to reset\n"); } /* check_pending * check for completion of pending control request * parameter: - * urb USB request block of completed request - * urb->context = hardware specific controller state structure + * ucs hardware specific controller state structure */ static void check_pending(struct bas_cardstate *ucs) { unsigned long flags; - IFNULLRET(ucs); - IFNULLRET(cardstate); - spin_lock_irqsave(&ucs->lock, flags); switch (ucs->pending) { case 0: @@ -336,8 +366,6 @@ static void check_pending(struct bas_cardstate *ucs) case HD_CLOSE_ATCHANNEL: if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) ucs->pending = 0; - //wake_up_interruptible(cs->initwait); - //FIXME need own wait queue? break; case HD_CLOSE_B1CHANNEL: if (!(atomic_read(&ucs->basstate) & BS_B1OPEN)) @@ -354,7 +382,9 @@ static void check_pending(struct bas_cardstate *ucs) * are handled separately and should never end up here */ default: - warn("unknown pending request 0x%02x cleared", ucs->pending); + dev_warn(&ucs->interface->dev, + "unknown pending request 0x%02x cleared\n", + ucs->pending); ucs->pending = 0; } @@ -372,58 +402,53 @@ static void check_pending(struct bas_cardstate *ucs) static void cmd_in_timeout(unsigned long data) { struct cardstate *cs = (struct cardstate *) data; - struct bas_cardstate *ucs; - unsigned long flags; - - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); + struct bas_cardstate *ucs = cs->hw.bas; - spin_lock_irqsave(&cs->lock, flags); - if (!atomic_read(&cs->connected)) { - dbg(DEBUG_USBREQ, "%s: disconnected", __func__); - spin_unlock_irqrestore(&cs->lock, flags); - return; - } if (!ucs->rcvbuf_size) { - dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); - spin_unlock_irqrestore(&cs->lock, flags); + gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); return; } - spin_unlock_irqrestore(&cs->lock, flags); - err("timeout reading AT response"); + dev_err(cs->dev, "timeout reading AT response\n"); error_reset(cs); //FIXME retry? } +/* set/clear bits in base connection state, return previous state + */ +inline static int update_basstate(struct bas_cardstate *ucs, + int set, int clear) +{ + unsigned long flags; + int state; -static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs); + spin_lock_irqsave(&ucs->lock, flags); + state = atomic_read(&ucs->basstate); + atomic_set(&ucs->basstate, (state & ~clear) | set); + spin_unlock_irqrestore(&ucs->lock, flags); + return state; +} /* atread_submit - * submit an HD_READ_ATMESSAGE command URB + * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout * parameters: * cs controller state structure * timeout timeout in 1/10 sec., 0: none * return value: * 0 on success - * -EINVAL if a NULL pointer is encountered somewhere * -EBUSY if another request is pending * any URB submission error code */ static int atread_submit(struct cardstate *cs, int timeout) { - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = cs->hw.bas; int ret; - IFNULLRETVAL(cs, -EINVAL); - ucs = cs->hw.bas; - IFNULLRETVAL(ucs, -EINVAL); - IFNULLRETVAL(ucs->urb_cmd_in, -EINVAL); + gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", + ucs->rcvbuf_size); - dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", ucs->rcvbuf_size); - - if (ucs->urb_cmd_in->status == -EINPROGRESS) { - err("could not submit HD_READ_ATMESSAGE: URB busy"); + if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) { + dev_err(cs->dev, + "could not submit HD_READ_ATMESSAGE: URB busy\n"); return -EBUSY; } @@ -433,19 +458,20 @@ static int atread_submit(struct cardstate *cs, int timeout) ucs->dr_cmd_in.wIndex = 0; ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, - usb_rcvctrlpipe(ucs->udev, 0), - (unsigned char*) & ucs->dr_cmd_in, - ucs->rcvbuf, ucs->rcvbuf_size, - read_ctrl_callback, cs->inbuf); + usb_rcvctrlpipe(ucs->udev, 0), + (unsigned char*) & ucs->dr_cmd_in, + ucs->rcvbuf, ucs->rcvbuf_size, + read_ctrl_callback, cs->inbuf); if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { - err("could not submit HD_READ_ATMESSAGE: %s", - get_usb_statmsg(ret)); + update_basstate(ucs, 0, BS_ATRDPEND); + dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", + get_usb_statmsg(ret)); return ret; } if (timeout > 0) { - dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); + gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10; ucs->timer_cmd_in.data = (unsigned long) cs; ucs->timer_cmd_in.function = cmd_in_timeout; @@ -454,26 +480,6 @@ static int atread_submit(struct cardstate *cs, int timeout) return 0; } -static void stopurbs(struct bas_bc_state *); -static int start_cbsend(struct cardstate *); - -/* set/clear bits in base connection state - */ -inline static void update_basstate(struct bas_cardstate *ucs, - int set, int clear) -{ - unsigned long flags; - int state; - - spin_lock_irqsave(&ucs->lock, flags); - state = atomic_read(&ucs->basstate); - state &= ~clear; - state |= set; - atomic_set(&ucs->basstate, state); - spin_unlock_irqrestore(&ucs->lock, flags); -} - - /* read_int_callback * USB completion handler for interrupt pipe input * called by the USB subsystem in interrupt context @@ -483,48 +489,49 @@ inline static void update_basstate(struct bas_cardstate *ucs, */ static void read_int_callback(struct urb *urb, struct pt_regs *regs) { - struct cardstate *cs; - struct bas_cardstate *ucs; + struct cardstate *cs = urb->context; + struct bas_cardstate *ucs = cs->hw.bas; struct bc_state *bcs; unsigned long flags; - int status; + int rc; unsigned l; int channel; - IFNULLRET(urb); - cs = (struct cardstate *) urb->context; - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); - - if (unlikely(!atomic_read(&cs->connected))) { - warn("%s: disconnected", __func__); - return; - } - switch (urb->status) { case 0: /* success */ break; - case -ENOENT: /* canceled */ - case -ECONNRESET: /* canceled (async) */ + case -ENOENT: /* cancelled */ + case -ECONNRESET: /* cancelled (async) */ case -EINPROGRESS: /* pending */ /* ignore silently */ - dbg(DEBUG_USBREQ, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + gig_dbg(DEBUG_USBREQ, "%s: %s", + __func__, get_usb_statmsg(urb->status)); + return; + case -ENODEV: /* device removed */ + case -ESHUTDOWN: /* device shut down */ + //FIXME use this as disconnect indicator? + gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); return; default: /* severe trouble */ - warn("interrupt read: %s", get_usb_statmsg(urb->status)); + dev_warn(cs->dev, "interrupt read: %s\n", + get_usb_statmsg(urb->status)); //FIXME corrective action? resubmission always ok? goto resubmit; } + /* drop incomplete packets even if the missing bytes wouldn't matter */ + if (unlikely(urb->actual_length < 3)) { + dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n", + urb->actual_length); + goto resubmit; + } + l = (unsigned) ucs->int_in_buf[1] + (((unsigned) ucs->int_in_buf[2]) << 8); - dbg(DEBUG_USBREQ, - "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", urb->actual_length, - (int)ucs->int_in_buf[0], l, - (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]); + gig_dbg(DEBUG_USBREQ, "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", + urb->actual_length, (int)ucs->int_in_buf[0], l, + (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]); channel = 0; @@ -570,62 +577,68 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) case HD_B1_FLOW_CONTROL: bcs = cs->bcs + channel; atomic_add((l - BAS_NORMFRAME) * BAS_CORRFRAMES, - &bcs->hw.bas->corrbytes); - dbg(DEBUG_ISO, - "Flow control (channel %d, sub %d): 0x%02x => %d", - channel, bcs->hw.bas->numsub, l, - atomic_read(&bcs->hw.bas->corrbytes)); + &bcs->hw.bas->corrbytes); + gig_dbg(DEBUG_ISO, + "Flow control (channel %d, sub %d): 0x%02x => %d", + channel, bcs->hw.bas->numsub, l, + atomic_read(&bcs->hw.bas->corrbytes)); break; case HD_RECEIVEATDATA_ACK: /* AT response ready to be received */ if (!l) { - warn("HD_RECEIVEATDATA_ACK with length 0 ignored"); + dev_warn(cs->dev, + "HD_RECEIVEATDATA_ACK with length 0 ignored\n"); break; } spin_lock_irqsave(&cs->lock, flags); if (ucs->rcvbuf_size) { - spin_unlock_irqrestore(&cs->lock, flags); - err("receive AT data overrun, %d bytes lost", l); - error_reset(cs); //FIXME reschedule - break; + /* throw away previous buffer - we have no queue */ + dev_err(cs->dev, + "receive AT data overrun, %d bytes lost\n", + ucs->rcvbuf_size); + kfree(ucs->rcvbuf); + ucs->rcvbuf_size = 0; } if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { spin_unlock_irqrestore(&cs->lock, flags); - err("%s: out of memory, %d bytes lost", __func__, l); - error_reset(cs); //FIXME reschedule + dev_err(cs->dev, "out of memory receiving AT data\n"); + error_reset(cs); break; } ucs->rcvbuf_size = l; ucs->retry_cmd_in = 0; - if ((status = atread_submit(cs, BAS_TIMEOUT)) < 0) { + if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) { kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; - error_reset(cs); //FIXME reschedule + if (rc != -ENODEV) + //FIXME corrective action? + error_reset(cs); } spin_unlock_irqrestore(&cs->lock, flags); break; case HD_RESET_INTERRUPT_PIPE_ACK: - dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK"); + gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK"); break; case HD_SUSPEND_END: - dbg(DEBUG_USBREQ, "HD_SUSPEND_END"); + gig_dbg(DEBUG_USBREQ, "HD_SUSPEND_END"); break; default: - warn("unknown Gigaset signal 0x%02x (%u) ignored", - (int) ucs->int_in_buf[0], l); + dev_warn(cs->dev, + "unknown Gigaset signal 0x%02x (%u) ignored\n", + (int) ucs->int_in_buf[0], l); } check_pending(ucs); resubmit: - status = usb_submit_urb(urb, SLAB_ATOMIC); - if (unlikely(status)) { - err("could not resubmit interrupt URB: %s", - get_usb_statmsg(status)); + rc = usb_submit_urb(urb, SLAB_ATOMIC); + if (unlikely(rc != 0 && rc != -ENODEV)) { + dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", + get_usb_rcmsg(rc)); error_reset(cs); } } @@ -639,31 +652,17 @@ resubmit: */ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) { - struct cardstate *cs; - struct bas_cardstate *ucs; - unsigned numbytes; - unsigned long flags; - struct inbuf_t *inbuf; + struct inbuf_t *inbuf = urb->context; + struct cardstate *cs = inbuf->cs; + struct bas_cardstate *ucs = cs->hw.bas; int have_data = 0; + unsigned numbytes; + int rc; - IFNULLRET(urb); - inbuf = (struct inbuf_t *) urb->context; - IFNULLRET(inbuf); - cs = inbuf->cs; - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); - - spin_lock_irqsave(&cs->lock, flags); - if (!atomic_read(&cs->connected)) { - warn("%s: disconnected", __func__); - spin_unlock_irqrestore(&cs->lock, flags); - return; - } + update_basstate(ucs, 0, BS_ATRDPEND); if (!ucs->rcvbuf_size) { - warn("%s: no receive in progress", __func__); - spin_unlock_irqrestore(&cs->lock, flags); + dev_warn(cs->dev, "%s: no receive in progress\n", __func__); return; } @@ -673,12 +672,14 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) case 0: /* normal completion */ numbytes = urb->actual_length; if (unlikely(numbytes == 0)) { - warn("control read: empty block received"); + dev_warn(cs->dev, + "control read: empty block received\n"); goto retry; } if (unlikely(numbytes != ucs->rcvbuf_size)) { - warn("control read: received %d chars, expected %d", - numbytes, ucs->rcvbuf_size); + dev_warn(cs->dev, + "control read: received %d chars, expected %d\n", + numbytes, ucs->rcvbuf_size); if (numbytes > ucs->rcvbuf_size) numbytes = ucs->rcvbuf_size; } @@ -694,27 +695,32 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) } break; - case -ENOENT: /* canceled */ - case -ECONNRESET: /* canceled (async) */ + case -ENOENT: /* cancelled */ + case -ECONNRESET: /* cancelled (async) */ case -EINPROGRESS: /* pending */ + case -ENODEV: /* device removed */ + case -ESHUTDOWN: /* device shut down */ /* no action necessary */ - dbg(DEBUG_USBREQ, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + gig_dbg(DEBUG_USBREQ, "%s: %s", + __func__, get_usb_statmsg(urb->status)); break; default: /* severe trouble */ - warn("control read: %s", get_usb_statmsg(urb->status)); + dev_warn(cs->dev, "control read: %s\n", + get_usb_statmsg(urb->status)); retry: if (ucs->retry_cmd_in++ < BAS_RETRY) { - notice("control read: retry %d", ucs->retry_cmd_in); - if (atread_submit(cs, BAS_TIMEOUT) >= 0) { - /* resubmitted - bypass regular exit block */ - spin_unlock_irqrestore(&cs->lock, flags); + dev_notice(cs->dev, "control read: retry %d\n", + ucs->retry_cmd_in); + rc = atread_submit(cs, BAS_TIMEOUT); + if (rc >= 0 || rc == -ENODEV) + /* resubmitted or disconnected */ + /* - bypass regular exit block */ return; - } } else { - err("control read: giving up after %d tries", - ucs->retry_cmd_in); + dev_err(cs->dev, + "control read: giving up after %d tries\n", + ucs->retry_cmd_in); } error_reset(cs); } @@ -722,9 +728,8 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; - spin_unlock_irqrestore(&cs->lock, flags); if (have_data) { - dbg(DEBUG_INTR, "%s-->BH", __func__); + gig_dbg(DEBUG_INTR, "%s-->BH", __func__); gigaset_schedule_event(cs); } } @@ -743,21 +748,19 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) unsigned long flags; int i, rc; - IFNULLRET(urb); - IFNULLRET(urb->context); - IFNULLRET(cardstate); - /* status codes not worth bothering the tasklet with */ - if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || - urb->status == -EINPROGRESS)) { - dbg(DEBUG_ISO, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + if (unlikely(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -EINPROGRESS || + urb->status == -ENODEV || + urb->status == -ESHUTDOWN)) { + gig_dbg(DEBUG_ISO, "%s: %s", + __func__, get_usb_statmsg(urb->status)); return; } - bcs = (struct bc_state *) urb->context; + bcs = urb->context; ubc = bcs->hw.bas; - IFNULLRET(ubc); spin_lock_irqsave(&ubc->isoinlock, flags); if (likely(ubc->isoindone == NULL)) { @@ -770,21 +773,24 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) 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 && - urb->iso_frame_desc[i].status != -EINPROGRESS)) { + urb->iso_frame_desc[i].status != + -EINPROGRESS)) ubc->loststatus = urb->iso_frame_desc[i].status; - } urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; } if (likely(atomic_read(&ubc->running))) { - urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */ + /* urb->dev is clobbered by USB subsystem */ + urb->dev = bcs->cs->hw.bas->udev; urb->transfer_flags = URB_ISO_ASAP; urb->number_of_packets = BAS_NUMFRAMES; - dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", __func__); + gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", + __func__); rc = usb_submit_urb(urb, SLAB_ATOMIC); - if (unlikely(rc != 0)) { - err("could not resubmit isochronous read URB: %s", - get_usb_statmsg(rc)); + if (unlikely(rc != 0 && rc != -ENODEV)) { + dev_err(bcs->cs->dev, + "could not resubmit isochronous read " + "URB: %s\n", get_usb_rcmsg(rc)); dump_urb(DEBUG_ISO, "isoc read", urb); error_hangup(bcs); } @@ -806,23 +812,20 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs) struct bas_bc_state *ubc; unsigned long flags; - IFNULLRET(urb); - IFNULLRET(urb->context); - IFNULLRET(cardstate); - /* status codes not worth bothering the tasklet with */ - if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || - urb->status == -EINPROGRESS)) { - dbg(DEBUG_ISO, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + if (unlikely(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -EINPROGRESS || + urb->status == -ENODEV || + urb->status == -ESHUTDOWN)) { + gig_dbg(DEBUG_ISO, "%s: %s", + __func__, get_usb_statmsg(urb->status)); return; } /* pass URB context to tasklet */ - ucx = (struct isow_urbctx_t *) urb->context; - IFNULLRET(ucx->bcs); + ucx = urb->context; ubc = ucx->bcs->hw.bas; - IFNULLRET(ubc); spin_lock_irqsave(&ubc->isooutlock, flags); ubc->isooutovfl = ubc->isooutdone; @@ -841,15 +844,11 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs) */ static int starturbs(struct bc_state *bcs) { + struct bas_bc_state *ubc = bcs->hw.bas; struct urb *urb; - struct bas_bc_state *ubc; int j, k; int rc; - IFNULLRETVAL(bcs, -EFAULT); - ubc = bcs->hw.bas; - IFNULLRETVAL(ubc, -EFAULT); - /* initialize L2 reception */ if (bcs->proto2 == ISDN_PROTO_L2_HDLC) bcs->inputstate |= INS_flag_hunt; @@ -859,7 +858,6 @@ static int starturbs(struct bc_state *bcs) for (k = 0; k < BAS_INURBS; k++) { urb = ubc->isoinurbs[k]; if (!urb) { - err("isoinurbs[%d]==NULL", k); rc = -EFAULT; goto error; } @@ -881,11 +879,8 @@ static int starturbs(struct bc_state *bcs) } dump_urb(DEBUG_ISO, "Initial isoc read", urb); - if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { - err("could not submit isochronous read URB %d: %s", - k, get_usb_statmsg(rc)); + if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) goto error; - } } /* initialize L2 transmission */ @@ -895,7 +890,6 @@ static int starturbs(struct bc_state *bcs) for (k = 0; k < BAS_OUTURBS; ++k) { urb = ubc->isoouturbs[k].urb; if (!urb) { - err("isoouturbs[%d].urb==NULL", k); rc = -EFAULT; goto error; } @@ -921,11 +915,8 @@ static int starturbs(struct bc_state *bcs) for (k = 0; k < 2; ++k) { dump_urb(DEBUG_ISO, "Initial isoc write", urb); rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC); - if (rc != 0) { - err("could not submit isochronous write URB %d: %s", - k, get_usb_statmsg(rc)); + if (rc != 0) goto error; - } } dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); ubc->isooutfree = &ubc->isoouturbs[2]; @@ -946,20 +937,20 @@ static void stopurbs(struct bas_bc_state *ubc) { int k, rc; - IFNULLRET(ubc); - atomic_set(&ubc->running, 0); for (k = 0; k < BAS_INURBS; ++k) { rc = usb_unlink_urb(ubc->isoinurbs[k]); - dbg(DEBUG_ISO, "%s: isoc input URB %d unlinked, result = %d", - __func__, k, rc); + gig_dbg(DEBUG_ISO, + "%s: isoc input URB %d unlinked, result = %s", + __func__, k, get_usb_rcmsg(rc)); } for (k = 0; k < BAS_OUTURBS; ++k) { rc = usb_unlink_urb(ubc->isoouturbs[k].urb); - dbg(DEBUG_ISO, "%s: isoc output URB %d unlinked, result = %d", - __func__, k, rc); + gig_dbg(DEBUG_ISO, + "%s: isoc output URB %d unlinked, result = %s", + __func__, k, get_usb_rcmsg(rc)); } } @@ -969,7 +960,7 @@ static void stopurbs(struct bas_bc_state *ubc) /* submit_iso_write_urb * fill and submit the next isochronous write URB * parameters: - * bcs B channel state structure + * ucx context structure containing URB * return value: * number of frames submitted in URB * 0 if URB not submitted because no data available (isooutbuf busy) @@ -977,19 +968,13 @@ static void stopurbs(struct bas_bc_state *ubc) */ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) { - struct urb *urb; - struct bas_bc_state *ubc; + struct urb *urb = ucx->urb; + struct bas_bc_state *ubc = ucx->bcs->hw.bas; struct usb_iso_packet_descriptor *ifd; int corrbytes, nframe, rc; - IFNULLRETVAL(ucx, -EFAULT); - urb = ucx->urb; - IFNULLRETVAL(urb, -EFAULT); - IFNULLRETVAL(ucx->bcs, -EFAULT); - ubc = ucx->bcs->hw.bas; - IFNULLRETVAL(ubc, -EFAULT); - - urb->dev = ucx->bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */ + /* urb->dev is clobbered by USB subsystem */ + urb->dev = ucx->bcs->cs->hw.bas->udev; urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = ubc->isooutbuf->data; urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data); @@ -1000,7 +985,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) /* compute frame length according to flow control */ ifd->length = BAS_NORMFRAME; if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) { - dbg(DEBUG_ISO, "%s: corrbytes=%d", __func__, corrbytes); + gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", + __func__, corrbytes); if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) corrbytes = BAS_HIGHFRAME - BAS_NORMFRAME; else if (corrbytes < BAS_LOWFRAME - BAS_NORMFRAME) @@ -1008,18 +994,21 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) ifd->length += corrbytes; atomic_add(-corrbytes, &ubc->corrbytes); } - //dbg(DEBUG_ISO, "%s: frame %d length=%d", __func__, nframe, ifd->length); /* retrieve block of data to send */ - ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length); + ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf, + ifd->length); if (ifd->offset < 0) { if (ifd->offset == -EBUSY) { - dbg(DEBUG_ISO, "%s: buffer busy at frame %d", - __func__, nframe); - /* tasklet will be restarted from gigaset_send_skb() */ + gig_dbg(DEBUG_ISO, + "%s: buffer busy at frame %d", + __func__, nframe); + /* tasklet will be restarted from + gigaset_send_skb() */ } else { - err("%s: buffer error %d at frame %d", - __func__, ifd->offset, nframe); + dev_err(ucx->bcs->cs->dev, + "%s: buffer error %d at frame %d\n", + __func__, ifd->offset, nframe); return ifd->offset; } break; @@ -1028,15 +1017,22 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) ifd->status = 0; ifd->actual_length = 0; } - if ((urb->number_of_packets = nframe) > 0) { - if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { - err("could not submit isochronous write URB: %s", - get_usb_statmsg(rc)); - dump_urb(DEBUG_ISO, "isoc write", urb); - return rc; - } - ++ubc->numsub; + if (unlikely(nframe == 0)) + return 0; /* no data to send */ + urb->number_of_packets = nframe; + + rc = usb_submit_urb(urb, SLAB_ATOMIC); + if (unlikely(rc)) { + if (rc == -ENODEV) + /* device removed - give up silently */ + gig_dbg(DEBUG_ISO, "%s: disconnected", __func__); + else + dev_err(ucx->bcs->cs->dev, + "could not submit isochronous write URB: %s\n", + get_usb_rcmsg(rc)); + return rc; } + ++ubc->numsub; return nframe; } @@ -1048,9 +1044,9 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) */ static void write_iso_tasklet(unsigned long data) { - struct bc_state *bcs; - struct bas_bc_state *ubc; - struct cardstate *cs; + struct bc_state *bcs = (struct bc_state *) data; + struct bas_bc_state *ubc = bcs->hw.bas; + struct cardstate *cs = bcs->cs; struct isow_urbctx_t *done, *next, *ovfl; struct urb *urb; struct usb_iso_packet_descriptor *ifd; @@ -1059,23 +1055,12 @@ static void write_iso_tasklet(unsigned long data) int i; struct sk_buff *skb; int len; - - bcs = (struct bc_state *) data; - IFNULLRET(bcs); - ubc = bcs->hw.bas; - IFNULLRET(ubc); - cs = bcs->cs; - IFNULLRET(cs); + int rc; /* loop while completed URBs arrive in time */ for (;;) { - if (unlikely(!atomic_read(&cs->connected))) { - warn("%s: disconnected", __func__); - return; - } - if (unlikely(!(atomic_read(&ubc->running)))) { - dbg(DEBUG_ISO, "%s: not running", __func__); + gig_dbg(DEBUG_ISO, "%s: not running", __func__); return; } @@ -1087,7 +1072,7 @@ static void write_iso_tasklet(unsigned long data) ubc->isooutovfl = NULL; spin_unlock_irqrestore(&ubc->isooutlock, flags); if (ovfl) { - err("isochronous write buffer underrun - buy a faster machine :-)"); + dev_err(cs->dev, "isochronous write buffer underrun\n"); error_hangup(bcs); break; } @@ -1100,7 +1085,8 @@ static void write_iso_tasklet(unsigned long data) ubc->isooutfree = NULL; spin_unlock_irqrestore(&ubc->isooutlock, flags); if (next) { - if (submit_iso_write_urb(next) <= 0) { + rc = submit_iso_write_urb(next); + if (unlikely(rc <= 0 && rc != -ENODEV)) { /* could not submit URB, put it back */ spin_lock_irqsave(&ubc->isooutlock, flags); if (ubc->isooutfree == NULL) { @@ -1110,7 +1096,8 @@ static void write_iso_tasklet(unsigned long data) spin_unlock_irqrestore(&ubc->isooutlock, flags); if (next) { /* couldn't put it back */ - err("losing isochronous write URB"); + dev_err(cs->dev, + "losing isochronous write URB\n"); error_hangup(bcs); } } @@ -1119,26 +1106,30 @@ static void write_iso_tasklet(unsigned long data) /* process completed URB */ urb = done->urb; switch (urb->status) { + case -EXDEV: /* partial completion */ + gig_dbg(DEBUG_ISO, "%s: URB partially completed", + __func__); + /* fall through - what's the difference anyway? */ case 0: /* normal completion */ - break; - case -EXDEV: /* inspect individual frames */ - /* assumptions (for lack of documentation): - * - actual_length bytes of the frame in error are successfully sent + /* inspect individual frames + * assumptions (for lack of documentation): + * - actual_length bytes of first frame in error are + * successfully sent * - all following frames are not sent at all */ - dbg(DEBUG_ISO, "%s: URB partially completed", __func__); - offset = done->limit; /* just in case */ + offset = done->limit; /* default (no error) */ for (i = 0; i < BAS_NUMFRAMES; i++) { ifd = &urb->iso_frame_desc[i]; if (ifd->status || ifd->actual_length != ifd->length) { - warn("isochronous write: frame %d: %s, " - "only %d of %d bytes sent", + dev_warn(cs->dev, + "isochronous write: frame %d: %s, " + "only %d of %d bytes sent\n", i, get_usb_statmsg(ifd->status), ifd->actual_length, ifd->length); offset = (ifd->offset + - ifd->actual_length) - % BAS_OUTBUFSIZE; + ifd->actual_length) + % BAS_OUTBUFSIZE; break; } } @@ -1148,25 +1139,26 @@ static void write_iso_tasklet(unsigned long data) ifd = &urb->iso_frame_desc[i]; if (ifd->status != -EINPROGRESS || ifd->actual_length != 0) { - warn("isochronous write: frame %d: %s, " - "%d of %d bytes sent", + dev_warn(cs->dev, + "isochronous write: frame %d: %s, " + "%d of %d bytes sent\n", i, get_usb_statmsg(ifd->status), ifd->actual_length, ifd->length); offset = (ifd->offset + - ifd->actual_length) - % BAS_OUTBUFSIZE; + ifd->actual_length) + % BAS_OUTBUFSIZE; break; } } #endif break; - case -EPIPE: //FIXME is this the code for "underrun"? - err("isochronous write stalled"); + case -EPIPE: /* stall - probably underrun */ + dev_err(cs->dev, "isochronous write stalled\n"); error_hangup(bcs); break; default: /* severe trouble */ - warn("isochronous write: %s", - get_usb_statmsg(urb->status)); + dev_warn(cs->dev, "isochronous write: %s\n", + get_usb_statmsg(urb->status)); } /* mark the write buffer area covered by this URB as free */ @@ -1180,7 +1172,8 @@ static void write_iso_tasklet(unsigned long data) spin_unlock_irqrestore(&ubc->isooutlock, flags); if (next) { /* only one URB still active - resubmit one */ - if (submit_iso_write_urb(next) <= 0) { + rc = submit_iso_write_urb(next); + if (unlikely(rc <= 0 && rc != -ENODEV)) { /* couldn't submit */ error_hangup(bcs); } @@ -1194,8 +1187,8 @@ static void write_iso_tasklet(unsigned long data) if (gigaset_isoc_buildframe(bcs, skb->data, len) == -EAGAIN) { /* insufficient buffer space, push back onto queue */ skb_queue_head(&bcs->squeue, skb); - dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d", - __func__, skb_queue_len(&bcs->squeue)); + gig_dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d", + __func__, skb_queue_len(&bcs->squeue)); break; } skb_pull(skb, len); @@ -1215,28 +1208,16 @@ static void write_iso_tasklet(unsigned long data) */ static void read_iso_tasklet(unsigned long data) { - struct bc_state *bcs; - struct bas_bc_state *ubc; - struct cardstate *cs; + struct bc_state *bcs = (struct bc_state *) data; + struct bas_bc_state *ubc = bcs->hw.bas; + struct cardstate *cs = bcs->cs; struct urb *urb; char *rcvbuf; unsigned long flags; int totleft, numbytes, offset, frame, rc; - bcs = (struct bc_state *) data; - IFNULLRET(bcs); - ubc = bcs->hw.bas; - IFNULLRET(ubc); - cs = bcs->cs; - IFNULLRET(cs); - /* loop while more completed URBs arrive in the meantime */ for (;;) { - if (!atomic_read(&cs->connected)) { - warn("%s: disconnected", __func__); - return; - } - /* retrieve URB */ spin_lock_irqsave(&ubc->isoinlock, flags); if (!(urb = ubc->isoindone)) { @@ -1245,38 +1226,44 @@ static void read_iso_tasklet(unsigned long data) } ubc->isoindone = NULL; if (unlikely(ubc->loststatus != -EINPROGRESS)) { - warn("isochronous read overrun, dropped URB with status: %s, %d bytes lost", - get_usb_statmsg(ubc->loststatus), ubc->isoinlost); + dev_warn(cs->dev, + "isochronous read overrun, " + "dropped URB with status: %s, %d bytes lost\n", + get_usb_statmsg(ubc->loststatus), + ubc->isoinlost); ubc->loststatus = -EINPROGRESS; } spin_unlock_irqrestore(&ubc->isoinlock, flags); if (unlikely(!(atomic_read(&ubc->running)))) { - dbg(DEBUG_ISO, "%s: channel not running, dropped URB with status: %s", - __func__, get_usb_statmsg(urb->status)); + gig_dbg(DEBUG_ISO, + "%s: channel not running, " + "dropped URB with status: %s", + __func__, get_usb_statmsg(urb->status)); return; } switch (urb->status) { case 0: /* normal completion */ break; - case -EXDEV: /* inspect individual frames (we do that anyway) */ - dbg(DEBUG_ISO, "%s: URB partially completed", __func__); + case -EXDEV: /* inspect individual frames + (we do that anyway) */ + gig_dbg(DEBUG_ISO, "%s: URB partially completed", + __func__); break; case -ENOENT: case -ECONNRESET: - dbg(DEBUG_ISO, "%s: URB canceled", __func__); - continue; /* -> skip */ - case -EINPROGRESS: /* huh? */ - dbg(DEBUG_ISO, "%s: URB still pending", __func__); + case -EINPROGRESS: + gig_dbg(DEBUG_ISO, "%s: %s", + __func__, get_usb_statmsg(urb->status)); continue; /* -> skip */ case -EPIPE: - err("isochronous read stalled"); + dev_err(cs->dev, "isochronous read stalled\n"); error_hangup(bcs); continue; /* -> skip */ default: /* severe trouble */ - warn("isochronous read: %s", - get_usb_statmsg(urb->status)); + dev_warn(cs->dev, "isochronous read: %s\n", + get_usb_statmsg(urb->status)); goto error; } @@ -1284,33 +1271,44 @@ static void read_iso_tasklet(unsigned long data) totleft = urb->actual_length; for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) { if (unlikely(urb->iso_frame_desc[frame].status)) { - warn("isochronous read: frame %d: %s", - frame, get_usb_statmsg(urb->iso_frame_desc[frame].status)); + dev_warn(cs->dev, + "isochronous read: frame %d: %s\n", + frame, + get_usb_statmsg( + urb->iso_frame_desc[frame].status)); break; } numbytes = urb->iso_frame_desc[frame].actual_length; if (unlikely(numbytes > BAS_MAXFRAME)) { - warn("isochronous read: frame %d: numbytes (%d) > BAS_MAXFRAME", - frame, numbytes); + dev_warn(cs->dev, + "isochronous read: frame %d: " + "numbytes (%d) > BAS_MAXFRAME\n", + frame, numbytes); break; } if (unlikely(numbytes > totleft)) { - warn("isochronous read: frame %d: numbytes (%d) > totleft (%d)", - frame, numbytes, totleft); + dev_warn(cs->dev, + "isochronous read: frame %d: " + "numbytes (%d) > totleft (%d)\n", + frame, numbytes, totleft); break; } offset = urb->iso_frame_desc[frame].offset; if (unlikely(offset + numbytes > BAS_INBUFSIZE)) { - warn("isochronous read: frame %d: offset (%d) + numbytes (%d) > BAS_INBUFSIZE", - frame, offset, numbytes); + dev_warn(cs->dev, + "isochronous read: frame %d: " + "offset (%d) + numbytes (%d) " + "> BAS_INBUFSIZE\n", + frame, offset, numbytes); break; } gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs); totleft -= numbytes; } if (unlikely(totleft > 0)) - warn("isochronous read: %d data bytes missing", - totleft); + dev_warn(cs->dev, + "isochronous read: %d data bytes missing\n", + totleft); error: /* URB processed, resubmit */ @@ -1318,12 +1316,15 @@ static void read_iso_tasklet(unsigned long data) urb->iso_frame_desc[frame].status = 0; urb->iso_frame_desc[frame].actual_length = 0; } - urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */ + /* urb->dev is clobbered by USB subsystem */ + urb->dev = bcs->cs->hw.bas->udev; urb->transfer_flags = URB_ISO_ASAP; urb->number_of_packets = BAS_NUMFRAMES; - if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { - err("could not resubmit isochronous read URB: %s", - get_usb_statmsg(rc)); + rc = usb_submit_urb(urb, SLAB_ATOMIC); + if (unlikely(rc != 0 && rc != -ENODEV)) { + dev_err(cs->dev, + "could not resubmit isochronous read URB: %s\n", + get_usb_rcmsg(rc)); dump_urb(DEBUG_ISO, "resubmit iso read", urb); error_hangup(bcs); } @@ -1341,15 +1342,10 @@ static void read_iso_tasklet(unsigned long data) static void req_timeout(unsigned long data) { struct bc_state *bcs = (struct bc_state *) data; - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = bcs->cs->hw.bas; int pending; unsigned long flags; - IFNULLRET(bcs); - IFNULLRET(bcs->cs); - ucs = bcs->cs->hw.bas; - IFNULLRET(ucs); - check_pending(ucs); spin_lock_irqsave(&ucs->lock, flags); @@ -1359,33 +1355,34 @@ static void req_timeout(unsigned long data) switch (pending) { case 0: /* no pending request */ - dbg(DEBUG_USBREQ, "%s: no request pending", __func__); + gig_dbg(DEBUG_USBREQ, "%s: no request pending", __func__); break; case HD_OPEN_ATCHANNEL: - err("timeout opening AT channel"); + dev_err(bcs->cs->dev, "timeout opening AT channel\n"); error_reset(bcs->cs); break; case HD_OPEN_B2CHANNEL: case HD_OPEN_B1CHANNEL: - err("timeout opening channel %d", bcs->channel + 1); + dev_err(bcs->cs->dev, "timeout opening channel %d\n", + bcs->channel + 1); error_hangup(bcs); break; case HD_CLOSE_ATCHANNEL: - err("timeout closing AT channel"); - //wake_up_interruptible(cs->initwait); - //FIXME need own wait queue? + dev_err(bcs->cs->dev, "timeout closing AT channel\n"); break; case HD_CLOSE_B2CHANNEL: case HD_CLOSE_B1CHANNEL: - err("timeout closing channel %d", bcs->channel + 1); + dev_err(bcs->cs->dev, "timeout closing channel %d\n", + bcs->channel + 1); break; default: - warn("request 0x%02x timed out, clearing", pending); + dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", + pending); } } @@ -1398,18 +1395,14 @@ static void req_timeout(unsigned long data) */ static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) { - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = urb->context; unsigned long flags; - IFNULLRET(urb); - IFNULLRET(urb->context); - IFNULLRET(cardstate); - - ucs = (struct bas_cardstate *) urb->context; spin_lock_irqsave(&ucs->lock, flags); if (urb->status && ucs->pending) { - err("control request 0x%02x failed: %s", - ucs->pending, get_usb_statmsg(urb->status)); + dev_err(&ucs->interface->dev, + "control request 0x%02x failed: %s\n", + ucs->pending, get_usb_statmsg(urb->status)); del_timer(&ucs->timer_ctrl); ucs->pending = 0; } @@ -1432,34 +1425,24 @@ static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) * timeout timeout in seconds (0: no timeout) * return value: * 0 on success - * -EINVAL if a NULL pointer is encountered somewhere * -EBUSY if another request is pending * any URB submission error code */ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) { - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = bcs->cs->hw.bas; int ret; unsigned long flags; - IFNULLRETVAL(bcs, -EINVAL); - IFNULLRETVAL(bcs->cs, -EINVAL); - ucs = bcs->cs->hw.bas; - IFNULLRETVAL(ucs, -EINVAL); - IFNULLRETVAL(ucs->urb_ctrl, -EINVAL); - - dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val); + gig_dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val); spin_lock_irqsave(&ucs->lock, flags); if (ucs->pending) { spin_unlock_irqrestore(&ucs->lock, flags); - err("submission of request 0x%02x failed: request 0x%02x still pending", - req, ucs->pending); - return -EBUSY; - } - if (ucs->urb_ctrl->status == -EINPROGRESS) { - spin_unlock_irqrestore(&ucs->lock, flags); - err("could not submit request 0x%02x: URB busy", req); + dev_err(bcs->cs->dev, + "submission of request 0x%02x failed: " + "request 0x%02x still pending\n", + req, ucs->pending); return -EBUSY; } @@ -1469,19 +1452,19 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) ucs->dr_ctrl.wIndex = 0; ucs->dr_ctrl.wLength = 0; usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - (unsigned char*) &ucs->dr_ctrl, NULL, 0, - write_ctrl_callback, ucs); + usb_sndctrlpipe(ucs->udev, 0), + (unsigned char*) &ucs->dr_ctrl, NULL, 0, + write_ctrl_callback, ucs); if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) { - err("could not submit request 0x%02x: %s", - req, get_usb_statmsg(ret)); + dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n", + req, get_usb_statmsg(ret)); spin_unlock_irqrestore(&ucs->lock, flags); return ret; } ucs->pending = req; if (timeout > 0) { - dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); + gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10; ucs->timer_ctrl.data = (unsigned long) bcs; ucs->timer_ctrl.function = req_timeout; @@ -1503,23 +1486,36 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) static int gigaset_init_bchannel(struct bc_state *bcs) { int req, ret; + unsigned long flags; - IFNULLRETVAL(bcs, -EINVAL); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (unlikely(!bcs->cs->connected)) { + gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + return -ENODEV; + } if ((ret = starturbs(bcs)) < 0) { - err("could not start isochronous I/O for channel %d", - bcs->channel + 1); - error_hangup(bcs); + dev_err(bcs->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); return ret; } req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { - err("could not open channel %d: %s", - bcs->channel + 1, get_usb_statmsg(ret)); + dev_err(bcs->cs->dev, "could not open channel B%d\n", + bcs->channel + 1); stopurbs(bcs->hw.bas); - error_hangup(bcs); + if (ret != -ENODEV) + error_hangup(bcs); } + + spin_unlock_irqrestore(&bcs->cs->lock, flags); return ret; } @@ -1536,20 +1532,30 @@ static int gigaset_init_bchannel(struct bc_state *bcs) static int gigaset_close_bchannel(struct bc_state *bcs) { int req, ret; + unsigned long flags; - IFNULLRETVAL(bcs, -EINVAL); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (unlikely(!bcs->cs->connected)) { + spin_unlock_irqrestore(&bcs->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))) { /* channel not running: just signal common.c */ + spin_unlock_irqrestore(&bcs->cs->lock, flags); gigaset_bchannel_down(bcs); return 0; } + /* 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) - err("could not submit HD_CLOSE_BxCHANNEL request: %s", - get_usb_statmsg(ret)); + dev_err(bcs->cs->dev, "closing channel B%d failed\n", + bcs->channel + 1); + + spin_unlock_irqrestore(&bcs->cs->lock, flags); return ret; } @@ -1564,17 +1570,13 @@ static int gigaset_close_bchannel(struct bc_state *bcs) */ static void complete_cb(struct cardstate *cs) { - struct cmdbuf_t *cb; - - IFNULLRET(cs); - cb = cs->cmdbuf; - IFNULLRET(cb); + struct cmdbuf_t *cb = cs->cmdbuf; /* unqueue completed buffer */ cs->cmdbytes -= cs->curlen; - dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, - "write_command: sent %u bytes, %u left", - cs->curlen, cs->cmdbytes); + gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, + "write_command: sent %u bytes, %u left", + cs->curlen, cs->cmdbytes); if ((cs->cmdbuf = cb->next) != NULL) { cs->cmdbuf->prev = NULL; cs->curlen = cs->cmdbuf->len; @@ -1589,8 +1591,6 @@ static void complete_cb(struct cardstate *cs) kfree(cb); } -static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len); - /* write_command_callback * USB completion handler for AT command transmission * called by the USB subsystem in interrupt context @@ -1600,40 +1600,43 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len); */ static void write_command_callback(struct urb *urb, struct pt_regs *regs) { - struct cardstate *cs; + struct cardstate *cs = urb->context; + struct bas_cardstate *ucs = cs->hw.bas; unsigned long flags; - struct bas_cardstate *ucs; - IFNULLRET(urb); - cs = (struct cardstate *) urb->context; - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); + update_basstate(ucs, 0, BS_ATWRPEND); /* check status */ switch (urb->status) { case 0: /* normal completion */ break; - case -ENOENT: /* canceled */ - case -ECONNRESET: /* canceled (async) */ + case -ENOENT: /* cancelled */ + case -ECONNRESET: /* cancelled (async) */ case -EINPROGRESS: /* pending */ + case -ENODEV: /* device removed */ + case -ESHUTDOWN: /* device shut down */ /* ignore silently */ - dbg(DEBUG_USBREQ, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + gig_dbg(DEBUG_USBREQ, "%s: %s", + __func__, get_usb_statmsg(urb->status)); return; default: /* any failure */ if (++ucs->retry_cmd_out > BAS_RETRY) { - warn("command write: %s, giving up after %d retries", - get_usb_statmsg(urb->status), ucs->retry_cmd_out); + dev_warn(cs->dev, + "command write: %s, " + "giving up after %d retries\n", + get_usb_statmsg(urb->status), + ucs->retry_cmd_out); break; } if (cs->cmdbuf == NULL) { - warn("command write: %s, cannot retry - cmdbuf gone", - get_usb_statmsg(urb->status)); + dev_warn(cs->dev, + "command write: %s, " + "cannot retry - cmdbuf gone\n", + get_usb_statmsg(urb->status)); break; } - notice("command write: %s, retry %d", - get_usb_statmsg(urb->status), ucs->retry_cmd_out); + dev_notice(cs->dev, "command write: %s, retry %d\n", + get_usb_statmsg(urb->status), ucs->retry_cmd_out); if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) /* resubmitted - bypass regular exit block */ return; @@ -1655,13 +1658,9 @@ static void write_command_callback(struct urb *urb, struct pt_regs *regs) static void atrdy_timeout(unsigned long data) { struct cardstate *cs = (struct cardstate *) data; - struct bas_cardstate *ucs; - - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); + struct bas_cardstate *ucs = cs->hw.bas; - warn("timeout waiting for HD_READY_SEND_ATDATA"); + dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n"); /* fake the missing signal - what else can I do? */ update_basstate(ucs, BS_ATREADY, BS_ATTIMER); @@ -1676,24 +1675,19 @@ static void atrdy_timeout(unsigned long data) * len length of command to send * return value: * 0 on success - * -EFAULT if a NULL pointer is encountered somewhere * -EBUSY if another request is pending * any URB submission error code */ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) { - struct bas_cardstate *ucs; - int ret; - - IFNULLRETVAL(cs, -EFAULT); - ucs = cs->hw.bas; - IFNULLRETVAL(ucs, -EFAULT); - IFNULLRETVAL(ucs->urb_cmd_out, -EFAULT); + struct bas_cardstate *ucs = cs->hw.bas; + int rc; - dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); + gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); - if (ucs->urb_cmd_out->status == -EINPROGRESS) { - err("could not submit HD_WRITE_ATMESSAGE: URB busy"); + if (update_basstate(ucs, BS_ATWRPEND, 0) & BS_ATWRPEND) { + dev_err(cs->dev, + "could not submit HD_WRITE_ATMESSAGE: URB busy\n"); return -EBUSY; } @@ -1706,25 +1700,22 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) usb_sndctrlpipe(ucs->udev, 0), (unsigned char*) &ucs->dr_cmd_out, buf, len, write_command_callback, cs); - - if ((ret = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC)) != 0) { - err("could not submit HD_WRITE_ATMESSAGE: %s", - get_usb_statmsg(ret)); - return ret; + rc = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC); + if (unlikely(rc)) { + update_basstate(ucs, 0, BS_ATWRPEND); + dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n", + get_usb_rcmsg(rc)); + return rc; } - /* submitted successfully */ - update_basstate(ucs, 0, BS_ATREADY); - - /* start timeout if necessary */ - if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) { - dbg(DEBUG_OUTPUT, - "setting ATREADY timeout of %d/10 secs", ATRDY_TIMEOUT); + /* submitted successfully, start timeout if necessary */ + if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) { + gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs", + ATRDY_TIMEOUT); ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10; ucs->timer_atrdy.data = (unsigned long) cs; ucs->timer_atrdy.function = atrdy_timeout; add_timer(&ucs->timer_atrdy); - update_basstate(ucs, BS_ATTIMER, 0); } return 0; } @@ -1740,21 +1731,16 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) static int start_cbsend(struct cardstate *cs) { struct cmdbuf_t *cb; - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = cs->hw.bas; unsigned long flags; int rc; int retval = 0; - IFNULLRETVAL(cs, -EFAULT); - ucs = cs->hw.bas; - IFNULLRETVAL(ucs, -EFAULT); - /* check if AT channel is open */ if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) { - dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, "AT channel not open"); + gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); if (rc < 0) { - err("could not open AT channel"); /* flush command queue */ spin_lock_irqsave(&cs->cmdlock, flags); while (cs->cmdbuf != NULL) @@ -1792,27 +1778,23 @@ static int start_cbsend(struct cardstate *cs) * cs controller state structure * buf command string to send * len number of bytes to send (max. IF_WRITEBUF) - * wake_tasklet tasklet to run when transmission is completed (NULL if none) + * wake_tasklet tasklet to run when transmission is completed + * (NULL if none) * return value: * number of bytes queued on success * error code < 0 on error */ static int gigaset_write_cmd(struct cardstate *cs, - const unsigned char *buf, int len, - struct tasklet_struct *wake_tasklet) + const unsigned char *buf, int len, + struct tasklet_struct *wake_tasklet) { struct cmdbuf_t *cb; unsigned long flags; int status; gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", len, buf, 0); - - if (!atomic_read(&cs->connected)) { - err("%s: not connected", __func__); - return -ENODEV; - } + DEBUG_TRANSCMD : DEBUG_LOCKCMD, + "CMD Transmit", len, buf); if (len <= 0) return 0; /* nothing to do */ @@ -1820,7 +1802,7 @@ static int gigaset_write_cmd(struct cardstate *cs, if (len > IF_WRITEBUF) len = IF_WRITEBUF; if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { - err("%s: out of memory", __func__); + dev_err(cs->dev, "%s: out of memory\n", __func__); return -ENOMEM; } @@ -1842,14 +1824,21 @@ static int gigaset_write_cmd(struct cardstate *cs, cs->lastcmdbuf = cb; spin_unlock_irqrestore(&cs->cmdlock, 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; + } status = start_cbsend(cs); - + spin_unlock_irqrestore(&cs->lock, flags); return status < 0 ? status : len; } /* gigaset_write_room * tty_driver.write_room interface routine - * return number of characters the driver will accept to be written via gigaset_write_cmd + * return number of characters the driver will accept to be written via + * gigaset_write_cmd * parameter: * controller state structure * return value: @@ -1904,12 +1893,32 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) */ static int gigaset_freebcshw(struct bc_state *bcs) { - if (!bcs->hw.bas) + struct bas_bc_state *ubc = bcs->hw.bas; + int i; + + if (!ubc) return 0; - if (bcs->hw.bas->isooutbuf) - kfree(bcs->hw.bas->isooutbuf); - kfree(bcs->hw.bas); + /* kill URBs and tasklets before freeing - better safe than sorry */ + atomic_set(&ubc->running, 0); + for (i = 0; i < BAS_OUTURBS; ++i) + if (ubc->isoouturbs[i].urb) { + gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d", + __func__, i); + usb_kill_urb(ubc->isoouturbs[i].urb); + usb_free_urb(ubc->isoouturbs[i].urb); + } + for (i = 0; i < BAS_INURBS; ++i) + if (ubc->isoinurbs[i]) { + gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d", + __func__, i); + usb_kill_urb(ubc->isoinurbs[i]); + usb_free_urb(ubc->isoinurbs[i]); + } + tasklet_kill(&ubc->sent_tasklet); + tasklet_kill(&ubc->rcvd_tasklet); + kfree(ubc->isooutbuf); + kfree(ubc); bcs->hw.bas = NULL; return 1; } @@ -1947,7 +1956,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) return 0; } tasklet_init(&ubc->sent_tasklet, - &write_iso_tasklet, (unsigned long) bcs); + &write_iso_tasklet, (unsigned long) bcs); spin_lock_init(&ubc->isoinlock); for (i = 0; i < BAS_INURBS; ++i) @@ -1968,7 +1977,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) ubc->shared0s = 0; ubc->stolen0s = 0; tasklet_init(&ubc->rcvd_tasklet, - &read_iso_tasklet, (unsigned long) bcs); + &read_iso_tasklet, (unsigned long) bcs); return 1; } @@ -1986,13 +1995,9 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) static void gigaset_freecshw(struct cardstate *cs) { - struct bas_cardstate *ucs = cs->hw.bas; - - del_timer(&ucs->timer_ctrl); - del_timer(&ucs->timer_atrdy); - del_timer(&ucs->timer_cmd_in); - + /* timers, URBs and rcvbuf are disposed of in disconnect */ kfree(cs->hw.bas); + cs->hw.bas = NULL; } static int gigaset_initcshw(struct cardstate *cs) @@ -2027,57 +2032,56 @@ static int gigaset_initcshw(struct cardstate *cs) */ static void freeurbs(struct cardstate *cs) { - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = cs->hw.bas; struct bas_bc_state *ubc; int i, j; - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); - for (j = 0; j < 2; ++j) { ubc = cs->bcs[j].hw.bas; - IFNULLCONT(ubc); for (i = 0; i < BAS_OUTURBS; ++i) if (ubc->isoouturbs[i].urb) { usb_kill_urb(ubc->isoouturbs[i].urb); - dbg(DEBUG_INIT, - "%s: isoc output URB %d/%d unlinked", - __func__, j, i); + gig_dbg(DEBUG_INIT, + "%s: isoc output URB %d/%d unlinked", + __func__, j, i); usb_free_urb(ubc->isoouturbs[i].urb); ubc->isoouturbs[i].urb = NULL; } for (i = 0; i < BAS_INURBS; ++i) if (ubc->isoinurbs[i]) { usb_kill_urb(ubc->isoinurbs[i]); - dbg(DEBUG_INIT, - "%s: isoc input URB %d/%d unlinked", - __func__, j, i); + gig_dbg(DEBUG_INIT, + "%s: isoc input URB %d/%d unlinked", + __func__, j, i); usb_free_urb(ubc->isoinurbs[i]); ubc->isoinurbs[i] = NULL; } } if (ucs->urb_int_in) { usb_kill_urb(ucs->urb_int_in); - dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", __func__); + gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", + __func__); usb_free_urb(ucs->urb_int_in); ucs->urb_int_in = NULL; } if (ucs->urb_cmd_out) { usb_kill_urb(ucs->urb_cmd_out); - dbg(DEBUG_INIT, "%s: command output URB unlinked", __func__); + gig_dbg(DEBUG_INIT, "%s: command output URB unlinked", + __func__); usb_free_urb(ucs->urb_cmd_out); ucs->urb_cmd_out = NULL; } if (ucs->urb_cmd_in) { usb_kill_urb(ucs->urb_cmd_in); - dbg(DEBUG_INIT, "%s: command input URB unlinked", __func__); + gig_dbg(DEBUG_INIT, "%s: command input URB unlinked", + __func__); usb_free_urb(ucs->urb_cmd_in); ucs->urb_cmd_in = NULL; } if (ucs->urb_ctrl) { usb_kill_urb(ucs->urb_ctrl); - dbg(DEBUG_INIT, "%s: control output URB unlinked", __func__); + gig_dbg(DEBUG_INIT, "%s: control output URB unlinked", + __func__); usb_free_urb(ucs->urb_ctrl); ucs->urb_ctrl = NULL; } @@ -2097,35 +2101,24 @@ static int gigaset_probe(struct usb_interface *interface, struct bas_bc_state *ubc; struct usb_endpoint_descriptor *endpoint; int i, j; - int ret; - - IFNULLRETVAL(udev, -ENODEV); - - 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)); + int rc; - /* See if the device offered us matches what we can accept */ - if ((le16_to_cpu(udev->descriptor.idVendor) != USB_GIGA_VENDOR_ID) || - (le16_to_cpu(udev->descriptor.idProduct) != USB_GIGA_PRODUCT_ID && - le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID && - le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID && - le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) { - dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__); - return -ENODEV; - } + 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)); /* set required alternate setting */ hostif = interface->cur_altsetting; if (hostif->desc.bAlternateSetting != 3) { - dbg(DEBUG_ANY, - "%s: wrong alternate setting %d - trying to switch", - __func__, hostif->desc.bAlternateSetting); + gig_dbg(DEBUG_ANY, + "%s: wrong alternate setting %d - trying to switch", + __func__, hostif->desc.bAlternateSetting); if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) { - warn("usb_set_interface failed, device %d interface %d altsetting %d", - udev->devnum, hostif->desc.bInterfaceNumber, - hostif->desc.bAlternateSetting); + dev_warn(&udev->dev, "usb_set_interface failed, " + "device %d interface %d altsetting %d\n", + udev->devnum, hostif->desc.bInterfaceNumber, + hostif->desc.bAlternateSetting); return -ENODEV; } hostif = interface->cur_altsetting; @@ -2134,68 +2127,50 @@ static int gigaset_probe(struct usb_interface *interface, /* Reject application specific interfaces */ if (hostif->desc.bInterfaceClass != 255) { - warn("%s: bInterfaceClass == %d", - __func__, hostif->desc.bInterfaceClass); + dev_warn(&udev->dev, "%s: bInterfaceClass == %d\n", + __func__, hostif->desc.bInterfaceClass); return -ENODEV; } - info("%s: Device matched (Vendor: 0x%x, Product: 0x%x)", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); + dev_info(&udev->dev, + "%s: Device matched (Vendor: 0x%x, Product: 0x%x)\n", + __func__, le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); cs = gigaset_getunassignedcs(driver); if (!cs) { - err("%s: no free cardstate", __func__); + dev_err(&udev->dev, "no free cardstate\n"); return -ENODEV; } ucs = cs->hw.bas; + + /* save off device structure ptrs for later use */ + usb_get_dev(udev); ucs->udev = udev; ucs->interface = interface; + cs->dev = &interface->dev; /* allocate URBs: * - one for the interrupt pipe * - three for the different uses of the default control pipe * - three for each isochronous pipe */ - ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL); - if (!ucs->urb_int_in) { - err("No free urbs available"); - goto error; - } - ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL); - if (!ucs->urb_cmd_in) { - err("No free urbs available"); - goto error; - } - ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL); - if (!ucs->urb_cmd_out) { - err("No free urbs available"); - goto error; - } - ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL); - if (!ucs->urb_ctrl) { - err("No free urbs available"); - goto error; - } + if (!(ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL)) || + !(ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL)) || + !(ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL)) || + !(ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL))) + goto allocerr; for (j = 0; j < 2; ++j) { ubc = cs->bcs[j].hw.bas; - for (i = 0; i < BAS_OUTURBS; ++i) { - ubc->isoouturbs[i].urb = - usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); - if (!ubc->isoouturbs[i].urb) { - err("No free urbs available"); - goto error; - } - } - for (i = 0; i < BAS_INURBS; ++i) { - ubc->isoinurbs[i] = - usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); - if (!ubc->isoinurbs[i]) { - err("No free urbs available"); - goto error; - } - } + for (i = 0; i < BAS_OUTURBS; ++i) + if (!(ubc->isoouturbs[i].urb = + usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL))) + goto allocerr; + for (i = 0; i < BAS_INURBS; ++i) + if (!(ubc->isoinurbs[i] = + usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL))) + goto allocerr; } ucs->rcvbuf = NULL; @@ -2204,35 +2179,37 @@ static int gigaset_probe(struct usb_interface *interface, /* Fill the interrupt urb and send it to the core */ endpoint = &hostif->endpoint[0].desc; usb_fill_int_urb(ucs->urb_int_in, udev, - usb_rcvintpipe(udev, - (endpoint->bEndpointAddress) & 0x0f), - ucs->int_in_buf, 3, read_int_callback, cs, - endpoint->bInterval); - ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL); - if (ret) { - err("could not submit interrupt URB: %s", get_usb_statmsg(ret)); + usb_rcvintpipe(udev, + (endpoint->bEndpointAddress) & 0x0f), + ucs->int_in_buf, 3, read_int_callback, cs, + endpoint->bInterval); + if ((rc = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL)) != 0) { + dev_err(cs->dev, "could not submit interrupt URB: %s\n", + get_usb_rcmsg(rc)); goto error; } /* tell the device that the driver is ready */ - if ((ret = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) + if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) goto error; /* tell common part that the device is ready */ if (startmode == SM_LOCKED) atomic_set(&cs->mstate, MS_LOCKED); - if (!gigaset_start(cs)) - goto error; /* save address of controller structure */ usb_set_intfdata(interface, cs); - /* set up device sysfs */ - gigaset_init_dev_sysfs(interface); + if (!gigaset_start(cs)) + goto error; + return 0; +allocerr: + dev_err(cs->dev, "could not allocate URBs\n"); error: freeurbs(cs); + usb_set_intfdata(interface, NULL); gigaset_unassign(cs); return -ENODEV; } @@ -2244,24 +2221,38 @@ static void gigaset_disconnect(struct usb_interface *interface) { struct cardstate *cs; struct bas_cardstate *ucs; - - /* clear device sysfs */ - gigaset_free_dev_sysfs(interface); + int j; cs = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - IFNULLRET(cs); ucs = cs->hw.bas; - IFNULLRET(ucs); - info("disconnecting GigaSet base"); + dev_info(cs->dev, "disconnecting Gigaset base\n"); + + /* mark base as not ready, all channels disconnected */ + atomic_set(&ucs->basstate, 0); + + /* tell LL all channels are down */ + //FIXME shouldn't gigaset_stop() do this? + for (j = 0; j < 2; ++j) + gigaset_bchannel_down(cs->bcs + j); + + /* stop driver (common part) */ gigaset_stop(cs); + + /* stop timers and URBs, free ressources */ + del_timer_sync(&ucs->timer_ctrl); + del_timer_sync(&ucs->timer_atrdy); + del_timer_sync(&ucs->timer_cmd_in); freeurbs(cs); + usb_set_intfdata(interface, NULL); kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; - atomic_set(&ucs->basstate, 0); + usb_put_dev(ucs->udev); + ucs->interface = NULL; + ucs->udev = NULL; + cs->dev = NULL; gigaset_unassign(cs); } @@ -2293,13 +2284,14 @@ static int __init bas_gigaset_init(void) /* allocate memory for our driver state and intialize it */ if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - GIGASET_DEVFSNAME, &gigops, - THIS_MODULE)) == NULL) + GIGASET_MODULENAME, GIGASET_DEVNAME, + GIGASET_DEVFSNAME, &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); + cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, + GIGASET_MODULENAME); if (!cardstate) goto error; @@ -2328,22 +2320,35 @@ error: if (cardstate) */ static void __exit bas_gigaset_exit(void) { + struct bas_cardstate *ucs = cardstate->hw.bas; + gigaset_blockdriver(driver); /* => probe will fail - * => no gigaset_start any more - */ + * => no gigaset_start any more + */ gigaset_shutdown(cardstate); /* from now on, no isdn callback should be possible */ - if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) { - dbg(DEBUG_ANY, "closing AT channel"); - if (req_submit(cardstate->bcs, - HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) { - /* successfully submitted - wait for completion */ - //wait_event_interruptible(cs->initwait, !cs->hw.bas->pending); - //FIXME need own wait queue? wakeup? - } + /* 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); } + atomic_set(&ucs->basstate, 0); /* deregister this driver with the USB subsystem */ usb_deregister(&gigaset_usb_driver); diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 6437199..e55767b 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -1,7 +1,7 @@ /* * Stuff used by all variants of the driver * - * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>, + * Copyright (c) 2001 by Stefan Eilers, * Hansjoerg Lipp <hjlipp@web.de>, * Tilman Schmidt <tilman@imap.cc>. * @@ -11,10 +11,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: common.c,v 1.104.4.22 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -23,7 +19,7 @@ #include <linux/moduleparam.h> /* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers <Eilers.Stefan@epost.de>" +#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers" #define DRIVER_DESC "Driver for Gigaset 307x" /* Module parameters */ @@ -32,21 +28,10 @@ EXPORT_SYMBOL_GPL(gigaset_debuglevel); module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(debug, "debug level"); -/*====================================================================== - Prototypes of internal functions - */ - -//static void gigaset_process_response(int resp_code, int parameter, -// struct at_state_t *at_state, -// unsigned char ** pstring); -static struct cardstate *alloc_cs(struct gigaset_driver *drv); -static void free_cs(struct cardstate *cs); -static void make_valid(struct cardstate *cs, unsigned mask); -static void make_invalid(struct cardstate *cs, unsigned mask); - -#define VALID_MINOR 0x01 -#define VALID_ID 0x02 -#define ASSIGNED 0x04 +/* driver state flags */ +#define VALID_MINOR 0x01 +#define VALID_ID 0x02 +#define ASSIGNED 0x04 /* bitwise byte inversion table */ __u8 gigaset_invtab[256] = { @@ -86,42 +71,40 @@ __u8 gigaset_invtab[256] = { EXPORT_SYMBOL_GPL(gigaset_invtab); void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, - size_t len, const unsigned char *buf, int from_user) + size_t len, const unsigned char *buf) { unsigned char outbuf[80]; - unsigned char inbuf[80 - 1]; - size_t numin; - const unsigned char *in; + unsigned char c; size_t space = sizeof outbuf - 1; unsigned char *out = outbuf; + size_t numin = len; - if (!from_user) { - in = buf; - numin = len; - } else { - numin = len < sizeof inbuf ? len : sizeof inbuf; - in = inbuf; - if (copy_from_user(inbuf, (const unsigned char __user *) buf, numin)) { - strncpy(inbuf, "<FAULT>", sizeof inbuf); - numin = sizeof "<FAULT>" - 1; + while (numin--) { + c = *buf++; + if (c == '~' || c == '^' || c == '\\') { + if (!space--) + break; + *out++ = '\\'; } - } - - for (; numin && space; --numin, ++in) { - --space; - if (*in >= 32) - *out++ = *in; - else { + if (c & 0x80) { + if (!space--) + break; + *out++ = '~'; + c ^= 0x80; + } + if (c < 0x20 || c == 0x7f) { + if (!space--) + break; *out++ = '^'; - if (space) { - *out++ = '@' + *in; - --space; - } + c ^= 0x40; } + if (!space--) + break; + *out++ = c; } *out = 0; - dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf); + gig_dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf); } EXPORT_SYMBOL_GPL(gigaset_dbg_buffer); @@ -146,11 +129,6 @@ int gigaset_enterconfigmode(struct cardstate *cs) { int i, r; - if (!atomic_read(&cs->connected)) { - err("not connected!"); - return -1; - } - cs->control_state = TIOCM_RTS; //FIXME r = setflags(cs, TIOCM_DTR, 200); @@ -174,7 +152,7 @@ int gigaset_enterconfigmode(struct cardstate *cs) return 0; error: - err("error %d on setuartbits!\n", -r); + dev_err(cs->dev, "error %d on setuartbits\n", -r); cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value? cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); @@ -187,13 +165,13 @@ static int test_timeout(struct at_state_t *at_state) return 0; if (--at_state->timer_expires) { - dbg(DEBUG_MCMD, "decreased timer of %p to %lu", - at_state, at_state->timer_expires); + gig_dbg(DEBUG_MCMD, "decreased timer of %p to %lu", + at_state, at_state->timer_expires); return 0; } if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, - atomic_read(&at_state->timer_index), NULL)) { + at_state->timer_index, NULL)) { //FIXME what should we do? } @@ -221,10 +199,10 @@ static void timer_tick(unsigned long data) if (test_timeout(at_state)) timeout = 1; - if (atomic_read(&cs->running)) { - mod_timer(&cs->timer, jiffies + GIG_TICK); + if (cs->running) { + mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK)); if (timeout) { - dbg(DEBUG_CMD, "scheduling timeout"); + gig_dbg(DEBUG_CMD, "scheduling timeout"); tasklet_schedule(&cs->event_tasklet); } } @@ -238,13 +216,14 @@ int gigaset_get_channel(struct bc_state *bcs) spin_lock_irqsave(&bcs->cs->lock, flags); if (bcs->use_count) { - dbg(DEBUG_ANY, "could not allocate channel %d", bcs->channel); + gig_dbg(DEBUG_ANY, "could not allocate channel %d", + bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return 0; } ++bcs->use_count; bcs->busy = 1; - dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); + gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return 1; } @@ -255,13 +234,13 @@ void gigaset_free_channel(struct bc_state *bcs) spin_lock_irqsave(&bcs->cs->lock, flags); if (!bcs->busy) { - dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); + gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return; } --bcs->use_count; bcs->busy = 0; - dbg(DEBUG_ANY, "freed channel %d", bcs->channel); + gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); } @@ -274,14 +253,14 @@ int gigaset_get_channels(struct cardstate *cs) for (i = 0; i < cs->channels; ++i) if (cs->bcs[i].use_count) { spin_unlock_irqrestore(&cs->lock, flags); - dbg(DEBUG_ANY, "could not allocated all channels"); + gig_dbg(DEBUG_ANY, "could not allocate all channels"); return 0; } for (i = 0; i < cs->channels; ++i) ++cs->bcs[i].use_count; spin_unlock_irqrestore(&cs->lock, flags); - dbg(DEBUG_ANY, "allocated all channels"); + gig_dbg(DEBUG_ANY, "allocated all channels"); return 1; } @@ -291,7 +270,7 @@ void gigaset_free_channels(struct cardstate *cs) unsigned long flags; int i; - dbg(DEBUG_ANY, "unblocking all channels"); + gig_dbg(DEBUG_ANY, "unblocking all channels"); spin_lock_irqsave(&cs->lock, flags); for (i = 0; i < cs->channels; ++i) --cs->bcs[i].use_count; @@ -303,7 +282,7 @@ void gigaset_block_channels(struct cardstate *cs) unsigned long flags; int i; - dbg(DEBUG_ANY, "blocking all channels"); + gig_dbg(DEBUG_ANY, "blocking all channels"); spin_lock_irqsave(&cs->lock, flags); for (i = 0; i < cs->channels; ++i) ++cs->bcs[i].use_count; @@ -314,25 +293,27 @@ static void clear_events(struct cardstate *cs) { struct event_t *ev; unsigned head, tail; + unsigned long flags; - /* no locking needed (no reader/writer allowed) */ + spin_lock_irqsave(&cs->ev_lock, flags); - head = atomic_read(&cs->ev_head); - tail = atomic_read(&cs->ev_tail); + head = cs->ev_head; + tail = cs->ev_tail; while (tail != head) { ev = cs->events + head; kfree(ev->ptr); - head = (head + 1) % MAX_EVENTS; } - atomic_set(&cs->ev_head, tail); + cs->ev_head = tail; + + spin_unlock_irqrestore(&cs->ev_lock, flags); } struct event_t *gigaset_add_event(struct cardstate *cs, - struct at_state_t *at_state, int type, - void *ptr, int parameter, void *arg) + struct at_state_t *at_state, int type, + void *ptr, int parameter, void *arg) { unsigned long flags; unsigned next, tail; @@ -340,9 +321,9 @@ struct event_t *gigaset_add_event(struct cardstate *cs, spin_lock_irqsave(&cs->ev_lock, flags); - tail = atomic_read(&cs->ev_tail); + tail = cs->ev_tail; next = (tail + 1) % MAX_EVENTS; - if (unlikely(next == atomic_read(&cs->ev_head))) + if (unlikely(next == cs->ev_head)) err("event queue full"); else { event = cs->events + tail; @@ -352,7 +333,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs, event->ptr = ptr; event->arg = arg; event->parameter = parameter; - atomic_set(&cs->ev_tail, next); + cs->ev_tail = next; } spin_unlock_irqrestore(&cs->ev_lock, flags); @@ -391,14 +372,14 @@ static void gigaset_freebcs(struct bc_state *bcs) { int i; - dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); + gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); if (!bcs->cs->ops->freebcshw(bcs)) { - dbg(DEBUG_INIT, "failed"); + gig_dbg(DEBUG_INIT, "failed"); } - dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); + gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); clear_at_state(&bcs->at_state); - dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); + gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); if (bcs->skb) dev_kfree_skb(bcs->skb); @@ -408,6 +389,52 @@ static void gigaset_freebcs(struct bc_state *bcs) } } +static struct cardstate *alloc_cs(struct gigaset_driver *drv) +{ + unsigned long flags; + unsigned i; + static struct cardstate *ret = NULL; + + spin_lock_irqsave(&drv->lock, flags); + for (i = 0; i < drv->minors; ++i) { + if (!(drv->flags[i] & VALID_MINOR)) { + drv->flags[i] = VALID_MINOR; + ret = drv->cs + i; + } + if (ret) + break; + } + 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); + drv->flags[cs->minor_index] = 0; + spin_unlock_irqrestore(&drv->lock, flags); +} + +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; + spin_unlock_irqrestore(&drv->lock, flags); +} + +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; + spin_unlock_irqrestore(&drv->lock, flags); +} + void gigaset_freecs(struct cardstate *cs) { int i; @@ -416,7 +443,7 @@ void gigaset_freecs(struct cardstate *cs) if (!cs) return; - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->bcs) goto f_cs; @@ -424,8 +451,9 @@ void gigaset_freecs(struct cardstate *cs) goto f_bcs; spin_lock_irqsave(&cs->lock, flags); - atomic_set(&cs->running, 0); - spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are not rescheduled below */ + cs->running = 0; + spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are + not rescheduled below */ tasklet_kill(&cs->event_tasklet); del_timer_sync(&cs->timer); @@ -434,7 +462,7 @@ void gigaset_freecs(struct cardstate *cs) default: gigaset_if_free(cs); - dbg(DEBUG_INIT, "clearing hw"); + gig_dbg(DEBUG_INIT, "clearing hw"); cs->ops->freecshw(cs); //FIXME cmdbuf @@ -443,36 +471,36 @@ void gigaset_freecs(struct cardstate *cs) case 2: /* error in initcshw */ /* Deregister from LL */ make_invalid(cs, VALID_ID); - dbg(DEBUG_INIT, "clearing iif"); + gig_dbg(DEBUG_INIT, "clearing iif"); gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); /* fall through */ case 1: /* error when regestering to LL */ - dbg(DEBUG_INIT, "clearing at_state"); + gig_dbg(DEBUG_INIT, "clearing at_state"); clear_at_state(&cs->at_state); dealloc_at_states(cs); /* fall through */ case 0: /* error in one call to initbcs */ for (i = 0; i < cs->channels; ++i) { - dbg(DEBUG_INIT, "clearing bcs[%d]", i); + gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); gigaset_freebcs(cs->bcs + i); } clear_events(cs); - dbg(DEBUG_INIT, "freeing inbuf"); + gig_dbg(DEBUG_INIT, "freeing inbuf"); kfree(cs->inbuf); } -f_bcs: dbg(DEBUG_INIT, "freeing bcs[]"); +f_bcs: gig_dbg(DEBUG_INIT, "freeing bcs[]"); kfree(cs->bcs); -f_cs: dbg(DEBUG_INIT, "freeing cs"); - up(&cs->sem); +f_cs: gig_dbg(DEBUG_INIT, "freeing cs"); + mutex_unlock(&cs->mutex); free_cs(cs); } EXPORT_SYMBOL_GPL(gigaset_freecs); void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, - struct cardstate *cs, int cid) + struct cardstate *cs, int cid) { int i; @@ -482,8 +510,8 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, at_state->pending_commands = 0; at_state->timer_expires = 0; at_state->timer_active = 0; - atomic_set(&at_state->timer_index, 0); - atomic_set(&at_state->seq_index, 0); + at_state->timer_index = 0; + at_state->seq_index = 0; at_state->ConState = 0; for (i = 0; i < STR_NUM; ++i) at_state->str_var[i] = NULL; @@ -501,7 +529,7 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, - struct cardstate *cs, int inputstate) + struct cardstate *cs, int inputstate) /* inbuf->read must be allocated before! */ { atomic_set(&inbuf->head, 0); @@ -512,9 +540,50 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, inbuf->inputstate = inputstate; } +/* append received bytes to inbuf */ +int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, + unsigned numbytes) +{ + unsigned n, head, tail, bytesleft; + + gig_dbg(DEBUG_INTR, "received %u bytes", numbytes); + + if (!numbytes) + return 0; + + bytesleft = numbytes; + tail = atomic_read(&inbuf->tail); + head = atomic_read(&inbuf->head); + gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); + + while (bytesleft) { + if (head > tail) + n = head - 1 - tail; + else if (head == 0) + n = (RBUFSIZE-1) - tail; + else + n = RBUFSIZE - tail; + if (!n) { + dev_err(inbuf->cs->dev, + "buffer overflow (%u bytes lost)", bytesleft); + break; + } + if (n > bytesleft) + n = bytesleft; + memcpy(inbuf->data + tail, src, n); + bytesleft -= n; + tail = (tail + n) % RBUFSIZE; + src += n; + } + gig_dbg(DEBUG_INTR, "setting tail to %u", tail); + atomic_set(&inbuf->tail, tail); + return numbytes != bytesleft; +} +EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); + /* Initialize the b-channel structure */ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, - struct cardstate *cs, int channel) + struct cardstate *cs, int channel) { int i; @@ -526,7 +595,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, bcs->trans_down = 0; bcs->trans_up = 0; - dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); + gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); gigaset_at_init(&bcs->at_state, bcs, cs, -1); bcs->rcvbytes = 0; @@ -535,7 +604,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, bcs->emptycount = 0; #endif - dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); + gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); bcs->fcs = PPP_INITFCS; bcs->inputstate = 0; if (cs->ignoreframes) { @@ -544,7 +613,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else { - warn("could not allocate skb"); + dev_warn(cs->dev, "could not allocate skb\n"); bcs->inputstate |= INS_skip_frame; } @@ -559,14 +628,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, for (i = 0; i < AT_NUM; ++i) bcs->commands[i] = NULL; - dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); + gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); if (cs->ops->initbcshw(bcs)) return bcs; -//error: - dbg(DEBUG_INIT, " failed"); + gig_dbg(DEBUG_INIT, " failed"); - dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); + gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); if (bcs->skb) dev_kfree_skb(bcs->skb); @@ -578,9 +646,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, * Calls hardware dependent gigaset_initcshw() function * Calls B channel initialization function gigaset_initbcs() for each B channel * parameters: - * drv hardware driver the device belongs to + * drv hardware driver the device belongs to * channels number of B channels supported by device - * onechannel !=0: B channel data and AT commands share one communication channel + * onechannel !=0: B channel data and AT commands share one + * communication channel * ==0: B channels have separate communication channels * ignoreframes number of frames to ignore after setting up B channel * cidmode !=0: start in CallID mode @@ -593,17 +662,18 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, int cidmode, const char *modulename) { struct cardstate *cs = NULL; + unsigned long flags; int i; - dbg(DEBUG_INIT, "allocating cs"); + gig_dbg(DEBUG_INIT, "allocating cs"); cs = alloc_cs(drv); if (!cs) goto error; - dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); + gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL); if (!cs->bcs) goto error; - dbg(DEBUG_INIT, "allocating inbuf"); + gig_dbg(DEBUG_INIT, "allocating inbuf"); cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); if (!cs->inbuf) goto error; @@ -613,19 +683,23 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->onechannel = onechannel; cs->ignoreframes = ignoreframes; INIT_LIST_HEAD(&cs->temp_at_states); - atomic_set(&cs->running, 0); + cs->running = 0; init_timer(&cs->timer); /* clear next & prev */ spin_lock_init(&cs->ev_lock); - atomic_set(&cs->ev_tail, 0); - atomic_set(&cs->ev_head, 0); - init_MUTEX_LOCKED(&cs->sem); - tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs); + cs->ev_tail = 0; + cs->ev_head = 0; + mutex_init(&cs->mutex); + mutex_lock(&cs->mutex); + + tasklet_init(&cs->event_tasklet, &gigaset_handle_event, + (unsigned long) cs); atomic_set(&cs->commands_pending, 0); cs->cur_at_seq = 0; cs->gotfwver = -1; cs->open_count = 0; + cs->dev = NULL; cs->tty = NULL; - atomic_set(&cs->cidmode, cidmode != 0); + cs->cidmode = cidmode != 0; //if(onechannel) { //FIXME cs->tabnocid = gigaset_tab_nocid_m10x; @@ -642,50 +716,43 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, atomic_set(&cs->mstate, MS_UNINITIALIZED); for (i = 0; i < channels; ++i) { - dbg(DEBUG_INIT, "setting up bcs[%d].read", i); + gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); if (!gigaset_initbcs(cs->bcs + i, cs, i)) goto error; } ++cs->cs_init; - dbg(DEBUG_INIT, "setting up at_state"); + gig_dbg(DEBUG_INIT, "setting up at_state"); spin_lock_init(&cs->lock); gigaset_at_init(&cs->at_state, NULL, cs, 0); cs->dle = 0; cs->cbytes = 0; - dbg(DEBUG_INIT, "setting up inbuf"); + gig_dbg(DEBUG_INIT, "setting up inbuf"); if (onechannel) { //FIXME distinction necessary? gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); } else gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); - atomic_set(&cs->connected, 0); + cs->connected = 0; + cs->isdn_up = 0; - dbg(DEBUG_INIT, "setting up cmdbuf"); + gig_dbg(DEBUG_INIT, "setting up cmdbuf"); cs->cmdbuf = cs->lastcmdbuf = NULL; spin_lock_init(&cs->cmdlock); cs->curlen = 0; cs->cmdbytes = 0; - /* - * Tell the ISDN4Linux subsystem (the LL) that - * a driver for a USB-Device is available ! - * If this is done, "isdnctrl" is able to bind a device for this driver even - * if no physical usb-device is currently connected. - * But this device will just be accessable if a physical USB device is connected - * (via "gigaset_probe") . - */ - dbg(DEBUG_INIT, "setting up iif"); + gig_dbg(DEBUG_INIT, "setting up iif"); if (!gigaset_register_to_LL(cs, modulename)) { - err("register_isdn=>error"); + err("register_isdn failed"); goto error; } make_valid(cs, VALID_ID); ++cs->cs_init; - dbg(DEBUG_INIT, "setting up hw"); + gig_dbg(DEBUG_INIT, "setting up hw"); if (!cs->ops->initcshw(cs)) goto error; @@ -693,27 +760,28 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, gigaset_if_init(cs); - atomic_set(&cs->running, 1); - cs->timer.data = (unsigned long) cs; - cs->timer.function = timer_tick; - cs->timer.expires = jiffies + GIG_TICK; + spin_lock_irqsave(&cs->lock, flags); + cs->running = 1; + spin_unlock_irqrestore(&cs->lock, flags); + setup_timer(&cs->timer, timer_tick, (unsigned long) cs); + cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK); /* FIXME: can jiffies increase too much until the timer is added? * Same problem(?) with mod_timer() in timer_tick(). */ add_timer(&cs->timer); - dbg(DEBUG_INIT, "cs initialized!"); - up(&cs->sem); + gig_dbg(DEBUG_INIT, "cs initialized"); + mutex_unlock(&cs->mutex); return cs; error: if (cs) - up(&cs->sem); - dbg(DEBUG_INIT, "failed"); + mutex_unlock(&cs->mutex); + gig_dbg(DEBUG_INIT, "failed"); gigaset_freecs(cs); return NULL; } EXPORT_SYMBOL_GPL(gigaset_initcs); -/* ReInitialize the b-channel structure */ /* e.g. called on hangup, disconnect */ +/* ReInitialize the b-channel structure on hangup */ void gigaset_bcs_reinit(struct bc_state *bcs) { struct sk_buff *skb; @@ -723,12 +791,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs) while ((skb = skb_dequeue(&bcs->squeue)) != NULL) dev_kfree_skb(skb); - spin_lock_irqsave(&cs->lock, flags); //FIXME + spin_lock_irqsave(&cs->lock, flags); clear_at_state(&bcs->at_state); bcs->at_state.ConState = 0; bcs->at_state.timer_active = 0; bcs->at_state.timer_expires = 0; - bcs->at_state.cid = -1; /* No CID defined */ + bcs->at_state.cid = -1; /* No CID defined */ spin_unlock_irqrestore(&cs->lock, flags); bcs->inputstate = 0; @@ -803,11 +871,14 @@ static void cleanup_cs(struct cardstate *cs) int gigaset_start(struct cardstate *cs) { - if (down_interruptible(&cs->sem)) + unsigned long flags; + + if (mutex_lock_interruptible(&cs->mutex)) return 0; - //info("USB device for Gigaset 307x now attached to Dev %d", ucs->minor); - atomic_set(&cs->connected, 1); + spin_lock_irqsave(&cs->lock, flags); + cs->connected = 1; + spin_unlock_irqrestore(&cs->lock, flags); if (atomic_read(&cs->mstate) != MS_LOCKED) { cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); @@ -826,23 +897,26 @@ int gigaset_start(struct cardstate *cs) goto error; } - dbg(DEBUG_CMD, "scheduling START"); + gig_dbg(DEBUG_CMD, "scheduling START"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); - up(&cs->sem); + /* set up device sysfs */ + gigaset_init_dev_sysfs(cs); + + mutex_unlock(&cs->mutex); return 1; error: - up(&cs->sem); + mutex_unlock(&cs->mutex); return 0; } EXPORT_SYMBOL_GPL(gigaset_start); void gigaset_shutdown(struct cardstate *cs) { - down(&cs->sem); + mutex_lock(&cs->mutex); cs->waiting = 1; @@ -851,11 +925,11 @@ void gigaset_shutdown(struct cardstate *cs) goto exit; } - dbg(DEBUG_CMD, "scheduling SHUTDOWN"); + gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN"); gigaset_schedule_event(cs); if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { - warn("aborted"); + warn("%s: aborted", __func__); //FIXME } @@ -872,15 +946,13 @@ void gigaset_shutdown(struct cardstate *cs) cleanup_cs(cs); exit: - up(&cs->sem); + mutex_unlock(&cs->mutex); } EXPORT_SYMBOL_GPL(gigaset_shutdown); void gigaset_stop(struct cardstate *cs) { - down(&cs->sem); - - atomic_set(&cs->connected, 0); + mutex_lock(&cs->mutex); cs->waiting = 1; @@ -889,21 +961,21 @@ void gigaset_stop(struct cardstate *cs) goto exit; } - dbg(DEBUG_CMD, "scheduling STOP"); + gig_dbg(DEBUG_CMD, "scheduling STOP"); gigaset_schedule_event(cs); if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { - warn("aborted"); + warn("%s: aborted", __func__); //FIXME } - /* Tell the LL that the device is not available .. */ - gigaset_i4l_cmd(cs, ISDN_STAT_STOP); // FIXME move to event layer? + /* clear device sysfs */ + gigaset_free_dev_sysfs(cs); cleanup_cs(cs); exit: - up(&cs->sem); + mutex_unlock(&cs->mutex); } EXPORT_SYMBOL_GPL(gigaset_stop); @@ -947,31 +1019,25 @@ void gigaset_debugdrivers(void) spin_lock_irqsave(&driver_lock, flags); list_for_each_entry(drv, &drivers, list) { - dbg(DEBUG_DRIVER, "driver %p", drv); + gig_dbg(DEBUG_DRIVER, "driver %p", drv); spin_lock(&drv->lock); for (i = 0; i < drv->minors; ++i) { - dbg(DEBUG_DRIVER, " index %u", i); - dbg(DEBUG_DRIVER, " flags 0x%02x", drv->flags[i]); + gig_dbg(DEBUG_DRIVER, " index %u", i); + gig_dbg(DEBUG_DRIVER, " flags 0x%02x", + drv->flags[i]); cs = drv->cs + i; - dbg(DEBUG_DRIVER, " cardstate %p", cs); - dbg(DEBUG_DRIVER, " minor_index %u", cs->minor_index); - dbg(DEBUG_DRIVER, " driver %p", cs->driver); - dbg(DEBUG_DRIVER, " i4l id %d", cs->myid); + gig_dbg(DEBUG_DRIVER, " cardstate %p", cs); + gig_dbg(DEBUG_DRIVER, " minor_index %u", + cs->minor_index); + gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver); + gig_dbg(DEBUG_DRIVER, " i4l id %d", cs->myid); } spin_unlock(&drv->lock); } spin_unlock_irqrestore(&driver_lock, flags); } -EXPORT_SYMBOL_GPL(gigaset_debugdrivers); - -struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) -{ - if (tty->index < 0 || tty->index >= tty->driver->num) - return NULL; - return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); -} -struct cardstate *gigaset_get_cs_by_minor(unsigned minor) +static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) { unsigned long flags; static struct cardstate *ret = NULL; @@ -994,6 +1060,13 @@ struct cardstate *gigaset_get_cs_by_minor(unsigned minor) return ret; } +struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) +{ + if (tty->index < 0 || tty->index >= tty->driver->num) + return NULL; + return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); +} + void gigaset_freedriver(struct gigaset_driver *drv) { unsigned long flags; @@ -1014,20 +1087,20 @@ EXPORT_SYMBOL_GPL(gigaset_freedriver); /* gigaset_initdriver * Allocate and initialize gigaset_driver structure. Initialize interface. * parameters: - * minor First minor number - * minors Number of minors this driver can handle - * procname Name of the driver (e.g. for /proc/tty/drivers, path in /proc/driver) - * devname Name of the device files (prefix without minor number) - * devfsname Devfs name of the device files without %d + * minor First minor number + * minors Number of minors this driver can handle + * procname Name of the driver + * devname Name of the device files (prefix without minor number) + * devfsname Devfs name of the device files without %d * return value: - * Pointer to the gigaset_driver structure on success, NULL on failure. + * Pointer to the gigaset_driver structure on success, NULL on failure. */ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, - const char *procname, - const char *devname, - const char *devfsname, - const struct gigaset_ops *ops, - struct module *owner) + const char *procname, + const char *devname, + const char *devfsname, + const struct gigaset_ops *ops, + struct module *owner) { struct gigaset_driver *drv; unsigned long flags; @@ -1036,8 +1109,9 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, drv = kmalloc(sizeof *drv, GFP_KERNEL); if (!drv) return NULL; + if (!try_module_get(owner)) - return NULL; + goto out1; drv->cs = NULL; drv->have_tty = 0; @@ -1051,10 +1125,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL); if (!drv->cs) - goto out1; + goto out2; + drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); if (!drv->flags) - goto out2; + goto out3; for (i = 0; i < minors; ++i) { drv->flags[i] = 0; @@ -1071,61 +1146,16 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, return drv; -out2: +out3: kfree(drv->cs); +out2: + module_put(owner); out1: kfree(drv); - module_put(owner); return NULL; } EXPORT_SYMBOL_GPL(gigaset_initdriver); -static struct cardstate *alloc_cs(struct gigaset_driver *drv) -{ - unsigned long flags; - unsigned i; - static struct cardstate *ret = NULL; - - spin_lock_irqsave(&drv->lock, flags); - for (i = 0; i < drv->minors; ++i) { - if (!(drv->flags[i] & VALID_MINOR)) { - drv->flags[i] = VALID_MINOR; - ret = drv->cs + i; - } - if (ret) - break; - } - 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); - drv->flags[cs->minor_index] = 0; - spin_unlock_irqrestore(&drv->lock, flags); -} - -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; - spin_unlock_irqrestore(&drv->lock, flags); -} - -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; - spin_unlock_irqrestore(&drv->lock, flags); -} - /* For drivers without fixed assignment device<->cardstate (usb) */ struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv) { diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index fdcb80b..18e05c0 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -1,7 +1,7 @@ /* * Stuff used by all variants of the driver * - * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>, + * Copyright (c) 2001 by Stefan Eilers, * Hansjoerg Lipp <hjlipp@web.de>, * Tilman Schmidt <tilman@imap.cc>. * @@ -11,82 +11,78 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: ev-layer.c,v 1.4.2.18 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" /* ========================================================== */ /* bit masks for pending commands */ -#define PC_INIT 0x004 -#define PC_DLE0 0x008 -#define PC_DLE1 0x010 -#define PC_CID 0x080 -#define PC_NOCID 0x100 -#define PC_HUP 0x002 -#define PC_DIAL 0x001 -#define PC_ACCEPT 0x040 -#define PC_SHUTDOWN 0x020 -#define PC_CIDMODE 0x200 -#define PC_UMMODE 0x400 +#define PC_DIAL 0x001 +#define PC_HUP 0x002 +#define PC_INIT 0x004 +#define PC_DLE0 0x008 +#define PC_DLE1 0x010 +#define PC_SHUTDOWN 0x020 +#define PC_ACCEPT 0x040 +#define PC_CID 0x080 +#define PC_NOCID 0x100 +#define PC_CIDMODE 0x200 +#define PC_UMMODE 0x400 /* types of modem responses */ -#define RT_NOTHING 0 -#define RT_ZSAU 1 -#define RT_RING 2 -#define RT_NUMBER 3 -#define RT_STRING 4 -#define RT_HEX 5 -#define RT_ZCAU 6 +#define RT_NOTHING 0 +#define RT_ZSAU 1 +#define RT_RING 2 +#define RT_NUMBER 3 +#define RT_STRING 4 +#define RT_HEX 5 +#define RT_ZCAU 6 /* Possible ASCII responses */ -#define RSP_OK 0 -//#define RSP_BUSY 1 -//#define RSP_CONNECT 2 -#define RSP_ZGCI 3 -#define RSP_RING 4 -#define RSP_ZAOC 5 -#define RSP_ZCSTR 6 -#define RSP_ZCFGT 7 -#define RSP_ZCFG 8 -#define RSP_ZCCR 9 -#define RSP_EMPTY 10 -#define RSP_ZLOG 11 -#define RSP_ZCAU 12 -#define RSP_ZMWI 13 -#define RSP_ZABINFO 14 -#define RSP_ZSMLSTCHG 15 -#define RSP_VAR 100 -#define RSP_ZSAU (RSP_VAR + VAR_ZSAU) -#define RSP_ZDLE (RSP_VAR + VAR_ZDLE) -#define RSP_ZVLS (RSP_VAR + VAR_ZVLS) -#define RSP_ZCTP (RSP_VAR + VAR_ZCTP) -#define RSP_STR (RSP_VAR + VAR_NUM) -#define RSP_NMBR (RSP_STR + STR_NMBR) -#define RSP_ZCPN (RSP_STR + STR_ZCPN) -#define RSP_ZCON (RSP_STR + STR_ZCON) -#define RSP_ZBC (RSP_STR + STR_ZBC) -#define RSP_ZHLC (RSP_STR + STR_ZHLC) -#define RSP_ERROR -1 /* ERROR */ -#define RSP_WRONG_CID -2 /* unknown cid in cmd */ -//#define RSP_EMPTY -3 -#define RSP_UNKNOWN -4 /* unknown response */ -#define RSP_FAIL -5 /* internal error */ -#define RSP_INVAL -6 /* invalid response */ - -#define RSP_NONE -19 -#define RSP_STRING -20 -#define RSP_NULL -21 -//#define RSP_RETRYFAIL -22 -//#define RSP_RETRY -23 -//#define RSP_SKIP -24 -#define RSP_INIT -27 -#define RSP_ANY -26 -#define RSP_LAST -28 -#define RSP_NODEV -9 +#define RSP_OK 0 +//#define RSP_BUSY 1 +//#define RSP_CONNECT 2 +#define RSP_ZGCI 3 +#define RSP_RING 4 +#define RSP_ZAOC 5 +#define RSP_ZCSTR 6 +#define RSP_ZCFGT 7 +#define RSP_ZCFG 8 +#define RSP_ZCCR 9 +#define RSP_EMPTY 10 +#define RSP_ZLOG 11 +#define RSP_ZCAU 12 +#define RSP_ZMWI 13 +#define RSP_ZABINFO 14 +#define RSP_ZSMLSTCHG 15 +#define RSP_VAR 100 +#define RSP_ZSAU (RSP_VAR + VAR_ZSAU) +#define RSP_ZDLE (RSP_VAR + VAR_ZDLE) +#define RSP_ZVLS (RSP_VAR + VAR_ZVLS) +#define RSP_ZCTP (RSP_VAR + VAR_ZCTP) +#define RSP_STR (RSP_VAR + VAR_NUM) +#define RSP_NMBR (RSP_STR + STR_NMBR) +#define RSP_ZCPN (RSP_STR + STR_ZCPN) +#define RSP_ZCON (RSP_STR + STR_ZCON) +#define RSP_ZBC (RSP_STR + STR_ZBC) +#define RSP_ZHLC (RSP_STR + STR_ZHLC) +#define RSP_ERROR -1 /* ERROR */ +#define RSP_WRONG_CID -2 /* unknown cid in cmd */ +//#define RSP_EMPTY -3 +#define RSP_UNKNOWN -4 /* unknown response */ +#define RSP_FAIL -5 /* internal error */ +#define RSP_INVAL -6 /* invalid response */ + +#define RSP_NONE -19 +#define RSP_STRING -20 +#define RSP_NULL -21 +//#define RSP_RETRYFAIL -22 +//#define RSP_RETRY -23 +//#define RSP_SKIP -24 +#define RSP_INIT -27 +#define RSP_ANY -26 +#define RSP_LAST -28 +#define RSP_NODEV -9 /* actions for process_response */ #define ACT_NOTHING 0 @@ -112,7 +108,7 @@ #define ACT_DISCONNECT 20 #define ACT_CONNECT 21 #define ACT_REMOTEREJECT 22 -#define ACT_CONNTIMEOUT 23 +#define ACT_CONNTIMEOUT 23 #define ACT_REMOTEHUP 24 #define ACT_ABORTHUP 25 #define ACT_ICALL 26 @@ -127,40 +123,40 @@ #define ACT_ERROR 35 #define ACT_ABORTCID 36 #define ACT_ZCAU 37 -#define ACT_NOTIFY_BC_DOWN 38 -#define ACT_NOTIFY_BC_UP 39 -#define ACT_DIAL 40 -#define ACT_ACCEPT 41 -#define ACT_PROTO_L2 42 -#define ACT_HUP 43 -#define ACT_IF_LOCK 44 -#define ACT_START 45 -#define ACT_STOP 46 -#define ACT_FAKEDLE0 47 -#define ACT_FAKEHUP 48 -#define ACT_FAKESDOWN 49 -#define ACT_SHUTDOWN 50 -#define ACT_PROC_CIDMODE 51 -#define ACT_UMODESET 52 -#define ACT_FAILUMODE 53 -#define ACT_CMODESET 54 -#define ACT_FAILCMODE 55 -#define ACT_IF_VER 56 +#define ACT_NOTIFY_BC_DOWN 38 +#define ACT_NOTIFY_BC_UP 39 +#define ACT_DIAL 40 +#define ACT_ACCEPT 41 +#define ACT_PROTO_L2 42 +#define ACT_HUP 43 +#define ACT_IF_LOCK 44 +#define ACT_START 45 +#define ACT_STOP 46 +#define ACT_FAKEDLE0 47 +#define ACT_FAKEHUP 48 +#define ACT_FAKESDOWN 49 +#define ACT_SHUTDOWN 50 +#define ACT_PROC_CIDMODE 51 +#define ACT_UMODESET 52 +#define ACT_FAILUMODE 53 +#define ACT_CMODESET 54 +#define ACT_FAILCMODE 55 +#define ACT_IF_VER 56 #define ACT_CMD 100 /* at command sequences */ -#define SEQ_NONE 0 -#define SEQ_INIT 100 -#define SEQ_DLE0 200 -#define SEQ_DLE1 250 -#define SEQ_CID 300 -#define SEQ_NOCID 350 -#define SEQ_HUP 400 -#define SEQ_DIAL 600 -#define SEQ_ACCEPT 720 -#define SEQ_SHUTDOWN 500 -#define SEQ_CIDMODE 10 -#define SEQ_UMMODE 11 +#define SEQ_NONE 0 +#define SEQ_INIT 100 +#define SEQ_DLE0 200 +#define SEQ_DLE1 250 +#define SEQ_CID 300 +#define SEQ_NOCID 350 +#define SEQ_HUP 400 +#define SEQ_DIAL 600 +#define SEQ_ACCEPT 720 +#define SEQ_SHUTDOWN 500 +#define SEQ_CIDMODE 10 +#define SEQ_UMMODE 11 // 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring @@ -175,7 +171,7 @@ struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */ // {ACT_TIMEOUT}}, {RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT, - {ACT_TIMEOUT}}, /* wait until device is ready */ + {ACT_TIMEOUT}}, /* wait until device is ready */ {EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */ {RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */ @@ -190,8 +186,8 @@ struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */ {RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}}, {EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0, - ACT_HUPMODEM, - ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */ + ACT_HUPMODEM, + ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */ {EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"}, {RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */ @@ -377,6 +373,9 @@ struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */ {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, + /* B channel closed (general case) */ + {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME + /* misc. */ {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME @@ -393,7 +392,7 @@ struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */ #if 0 -static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen uebernehmen +static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME { /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ @@ -401,7 +400,7 @@ static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen ueberne {RSP_LAST,0,0,0,0,0,0} }; -static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen uebernehmen +static struct reply_t tab_cid[] = /* no dle mode */ //FIXME { /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ @@ -412,30 +411,30 @@ static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen ueberneh static struct resp_type_t resp_type[]= { - /*{"", RSP_EMPTY, RT_NOTHING},*/ - {"OK", RSP_OK, RT_NOTHING}, - {"ERROR", RSP_ERROR, RT_NOTHING}, - {"ZSAU", RSP_ZSAU, RT_ZSAU}, - {"ZCAU", RSP_ZCAU, RT_ZCAU}, - {"RING", RSP_RING, RT_RING}, - {"ZGCI", RSP_ZGCI, RT_NUMBER}, - {"ZVLS", RSP_ZVLS, RT_NUMBER}, - {"ZCTP", RSP_ZCTP, RT_NUMBER}, - {"ZDLE", RSP_ZDLE, RT_NUMBER}, - {"ZCFGT", RSP_ZCFGT, RT_NUMBER}, - {"ZCCR", RSP_ZCCR, RT_NUMBER}, - {"ZMWI", RSP_ZMWI, RT_NUMBER}, - {"ZHLC", RSP_ZHLC, RT_STRING}, - {"ZBC", RSP_ZBC, RT_STRING}, - {"NMBR", RSP_NMBR, RT_STRING}, - {"ZCPN", RSP_ZCPN, RT_STRING}, - {"ZCON", RSP_ZCON, RT_STRING}, - {"ZAOC", RSP_ZAOC, RT_STRING}, - {"ZCSTR", RSP_ZCSTR, RT_STRING}, - {"ZCFG", RSP_ZCFG, RT_HEX}, - {"ZLOG", RSP_ZLOG, RT_NOTHING}, - {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, - {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, + /*{"", RSP_EMPTY, RT_NOTHING},*/ + {"OK", RSP_OK, RT_NOTHING}, + {"ERROR", RSP_ERROR, RT_NOTHING}, + {"ZSAU", RSP_ZSAU, RT_ZSAU}, + {"ZCAU", RSP_ZCAU, RT_ZCAU}, + {"RING", RSP_RING, RT_RING}, + {"ZGCI", RSP_ZGCI, RT_NUMBER}, + {"ZVLS", RSP_ZVLS, RT_NUMBER}, + {"ZCTP", RSP_ZCTP, RT_NUMBER}, + {"ZDLE", RSP_ZDLE, RT_NUMBER}, + {"ZCFGT", RSP_ZCFGT, RT_NUMBER}, + {"ZCCR", RSP_ZCCR, RT_NUMBER}, + {"ZMWI", RSP_ZMWI, RT_NUMBER}, + {"ZHLC", RSP_ZHLC, RT_STRING}, + {"ZBC", RSP_ZBC, RT_STRING}, + {"NMBR", RSP_NMBR, RT_STRING}, + {"ZCPN", RSP_ZCPN, RT_STRING}, + {"ZCON", RSP_ZCON, RT_STRING}, + {"ZAOC", RSP_ZAOC, RT_STRING}, + {"ZCSTR", RSP_ZCSTR, RT_STRING}, + {"ZCFG", RSP_ZCFG, RT_HEX}, + {"ZLOG", RSP_ZLOG, RT_NOTHING}, + {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, + {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, {NULL,0,0} }; @@ -446,9 +445,7 @@ static int isdn_getnum(char *p) { int v = -1; - IFNULLRETVAL(p, -1); - - dbg(DEBUG_TRANSCMD, "string: %s", p); + gig_dbg(DEBUG_TRANSCMD, "string: %s", p); while (*p >= '0' && *p <= '9') v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0'); @@ -465,9 +462,7 @@ static int isdn_gethex(char *p) int v = 0; int c; - IFNULLRETVAL(p, -1); - - dbg(DEBUG_TRANSCMD, "string: %s", p); + gig_dbg(DEBUG_TRANSCMD, "string: %s", p); if (!*p) return -1; @@ -490,14 +485,6 @@ static int isdn_gethex(char *p) return v; } -static inline void new_index(atomic_t *index, int max) -{ - if (atomic_read(index) == max) //FIXME race? - atomic_set(index, 0); - else - atomic_inc(index); -} - /* retrieve CID from parsed response * returns 0 if no CID, -1 if invalid CID, or CID value 1..65535 */ @@ -536,16 +523,14 @@ void gigaset_handle_modem_response(struct cardstate *cs) int cid; int rawstring; - IFNULLRET(cs); - len = cs->cbytes; if (!len) { /* ignore additional LFs/CRs (M10x config mode or cx100) */ - dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]); + gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]); return; } cs->respdata[len] = 0; - dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata); + gig_dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata); argv[0] = cs->respdata; params = 1; if (cs->at_state.getstring) { @@ -561,7 +546,8 @@ void gigaset_handle_modem_response(struct cardstate *cs) case ',': case '=': if (params > MAX_REC_PARAMS) { - warn("too many parameters in response"); + dev_warn(cs->dev, + "too many parameters in response\n"); /* need last parameter (might be CID) */ params--; } @@ -572,33 +558,33 @@ void gigaset_handle_modem_response(struct cardstate *cs) cid = params > 1 ? cid_of_response(argv[params-1]) : 0; if (cid < 0) { gigaset_add_event(cs, &cs->at_state, RSP_INVAL, - NULL, 0, NULL); + NULL, 0, NULL); return; } for (j = 1; j < params; ++j) argv[j][-1] = 0; - dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]); + gig_dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]); if (cid) { --params; - dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]); + gig_dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]); } - dbg(DEBUG_TRANSCMD, "available params: %d", params - 1); + gig_dbg(DEBUG_TRANSCMD, "available params: %d", params - 1); for (j = 1; j < params; j++) - dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]); + gig_dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]); } spin_lock_irqsave(&cs->ev_lock, flags); - head = atomic_read(&cs->ev_head); - tail = atomic_read(&cs->ev_tail); + head = cs->ev_head; + tail = cs->ev_tail; abort = 1; curarg = 0; while (curarg < params) { next = (tail + 1) % MAX_EVENTS; if (unlikely(next == head)) { - err("event queue full"); + dev_err(cs->dev, "event queue full\n"); break; } @@ -619,8 +605,9 @@ void gigaset_handle_modem_response(struct cardstate *cs) if (!rt->response) { event->type = RSP_UNKNOWN; - warn("unknown modem response: %s", - argv[curarg]); + dev_warn(cs->dev, + "unknown modem response: %s\n", + argv[curarg]); break; } @@ -636,7 +623,8 @@ void gigaset_handle_modem_response(struct cardstate *cs) break; case RT_RING: if (!cid) { - err("received RING without CID!"); + dev_err(cs->dev, + "received RING without CID!\n"); event->type = RSP_INVAL; abort = 1; } else { @@ -664,27 +652,25 @@ void gigaset_handle_modem_response(struct cardstate *cs) event->parameter = ZSAU_DISCONNECT_REQ; else { event->parameter = ZSAU_UNKNOWN; - warn("%s: unknown parameter %s after ZSAU", - __func__, argv[curarg]); + dev_warn(cs->dev, + "%s: unknown parameter %s after ZSAU\n", + __func__, argv[curarg]); } ++curarg; break; case RT_STRING: if (curarg < params) { - len = strlen(argv[curarg]) + 1; - event->ptr = kmalloc(len, GFP_ATOMIC); - if (event->ptr) - memcpy(event->ptr, argv[curarg], len); - else - err("no memory for string!"); + event->ptr = kstrdup(argv[curarg], GFP_ATOMIC); + if (!event->ptr) + dev_err(cs->dev, "out of memory\n"); ++curarg; } #ifdef CONFIG_GIGASET_DEBUG if (!event->ptr) - dbg(DEBUG_CMD, "string==NULL"); + gig_dbg(DEBUG_CMD, "string==NULL"); else - dbg(DEBUG_CMD, - "string==%s", (char *) event->ptr); + gig_dbg(DEBUG_CMD, "string==%s", + (char *) event->ptr); #endif break; case RT_ZCAU: @@ -694,7 +680,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) j = isdn_gethex(argv[curarg + 1]); if (i >= 0 && i < 256 && j >= 0 && j < 256) event->parameter = (unsigned) i << 8 - | j; + | j; curarg += 2; } else curarg = params - 1; @@ -712,7 +698,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) } else event->parameter = -1; #ifdef CONFIG_GIGASET_DEBUG - dbg(DEBUG_CMD, "parameter==%d", event->parameter); + gig_dbg(DEBUG_CMD, "parameter==%d", event->parameter); #endif break; } @@ -724,12 +710,13 @@ void gigaset_handle_modem_response(struct cardstate *cs) break; } - atomic_set(&cs->ev_tail, tail); + cs->ev_tail = tail; spin_unlock_irqrestore(&cs->ev_lock, flags); if (curarg != params) - dbg(DEBUG_ANY, "invalid number of processed parameters: %d/%d", - curarg, params); + gig_dbg(DEBUG_ANY, + "invalid number of processed parameters: %d/%d", + curarg, params); } EXPORT_SYMBOL_GPL(gigaset_handle_modem_response); @@ -739,23 +726,19 @@ EXPORT_SYMBOL_GPL(gigaset_handle_modem_response); static void disconnect(struct at_state_t **at_state_p) { unsigned long flags; - struct bc_state *bcs; - struct cardstate *cs; - - IFNULLRET(at_state_p); - IFNULLRET(*at_state_p); - bcs = (*at_state_p)->bcs; - cs = (*at_state_p)->cs; - IFNULLRET(cs); + struct bc_state *bcs = (*at_state_p)->bcs; + struct cardstate *cs = (*at_state_p)->cs; - new_index(&(*at_state_p)->seq_index, MAX_SEQ_INDEX); + spin_lock_irqsave(&cs->lock, flags); + ++(*at_state_p)->seq_index; /* revert to selected idle mode */ - if (!atomic_read(&cs->cidmode)) { + if (!cs->cidmode) { cs->at_state.pending_commands |= PC_UMMODE; atomic_set(&cs->commands_pending, 1); //FIXME - dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); + gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); } + spin_unlock_irqrestore(&cs->lock, flags); if (bcs) { /* B channel assigned: invoke hardware specific handler */ @@ -777,7 +760,7 @@ static void disconnect(struct at_state_t **at_state_p) * The structure should be freed by calling disconnect() after use. */ static inline struct at_state_t *get_free_channel(struct cardstate *cs, - int cid) + int cid) /* cids: >0: siemens-cid 0: without cid -1: no cid assigned yet @@ -826,7 +809,7 @@ static void init_failed(struct cardstate *cs, int mode) static void schedule_init(struct cardstate *cs, int state) { if (cs->at_state.pending_commands & PC_INIT) { - dbg(DEBUG_CMD, "not scheduling PC_INIT again"); + gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); return; } atomic_set(&cs->mstate, state); @@ -834,52 +817,56 @@ static void schedule_init(struct cardstate *cs, int state) gigaset_block_channels(cs); cs->at_state.pending_commands |= PC_INIT; atomic_set(&cs->commands_pending, 1); - dbg(DEBUG_CMD, "Scheduling PC_INIT"); + gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); } -/* Add "AT" to a command, add the cid, dle encode it, send the result to the hardware. */ +/* Add "AT" to a command, add the cid, dle encode it, send the result to the + hardware. */ static void send_command(struct cardstate *cs, const char *cmd, int cid, - int dle, gfp_t kmallocflags) + int dle, gfp_t kmallocflags) { size_t cmdlen, buflen; char *cmdpos, *cmdbuf, *cmdtail; cmdlen = strlen(cmd); buflen = 11 + cmdlen; + if (unlikely(buflen <= cmdlen)) { + dev_err(cs->dev, "integer overflow in buflen\n"); + return; + } - if (likely(buflen > cmdlen)) { - cmdbuf = kmalloc(buflen, kmallocflags); - if (likely(cmdbuf != NULL)) { - cmdpos = cmdbuf + 9; - cmdtail = cmdpos + cmdlen; - memcpy(cmdpos, cmd, cmdlen); - - if (cid > 0 && cid <= 65535) { - do { - *--cmdpos = '0' + cid % 10; - cid /= 10; - ++cmdlen; - } while (cid); - } + cmdbuf = kmalloc(buflen, kmallocflags); + if (unlikely(!cmdbuf)) { + dev_err(cs->dev, "out of memory\n"); + return; + } - cmdlen += 2; - *--cmdpos = 'T'; - *--cmdpos = 'A'; + cmdpos = cmdbuf + 9; + cmdtail = cmdpos + cmdlen; + memcpy(cmdpos, cmd, cmdlen); - if (dle) { - cmdlen += 4; - *--cmdpos = '('; - *--cmdpos = 0x10; - *cmdtail++ = 0x10; - *cmdtail++ = ')'; - } + if (cid > 0 && cid <= 65535) { + do { + *--cmdpos = '0' + cid % 10; + cid /= 10; + ++cmdlen; + } while (cid); + } - cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL); - kfree(cmdbuf); - } else - err("no memory for command buffer"); - } else - err("overflow in buflen"); + cmdlen += 2; + *--cmdpos = 'T'; + *--cmdpos = 'A'; + + if (dle) { + cmdlen += 4; + *--cmdpos = '('; + *--cmdpos = 0x10; + *cmdtail++ = 0x10; + *cmdtail++ = ')'; + } + + cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL); + kfree(cmdbuf); } static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid) @@ -910,9 +897,6 @@ static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid) static void bchannel_down(struct bc_state *bcs) { - IFNULLRET(bcs); - IFNULLRET(bcs->cs); - if (bcs->chstate & CHS_B_UP) { bcs->chstate &= ~CHS_B_UP; gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); @@ -930,16 +914,15 @@ static void bchannel_down(struct bc_state *bcs) static void bchannel_up(struct bc_state *bcs) { - IFNULLRET(bcs); - if (!(bcs->chstate & CHS_D_UP)) { - notice("%s: D channel not up", __func__); + dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__); bcs->chstate |= CHS_D_UP; gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); } if (bcs->chstate & CHS_B_UP) { - notice("%s: B channel already up", __func__); + dev_notice(bcs->cs->dev, "%s: B channel already up\n", + __func__); return; } @@ -947,17 +930,21 @@ static void bchannel_up(struct bc_state *bcs) gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); } -static void start_dial(struct at_state_t *at_state, void *data, int seq_index) +static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index) { struct bc_state *bcs = at_state->bcs; struct cardstate *cs = at_state->cs; int retval; + unsigned long flags; bcs->chstate |= CHS_NOTIFY_LL; - //atomic_set(&bcs->status, BCS_INIT); - if (atomic_read(&at_state->seq_index) != seq_index) + spin_lock_irqsave(&cs->lock, flags); + if (at_state->seq_index != seq_index) { + spin_unlock_irqrestore(&cs->lock, flags); goto error; + } + spin_unlock_irqrestore(&cs->lock, flags); retval = gigaset_isdn_setup_dial(at_state, data); if (retval != 0) @@ -965,20 +952,14 @@ static void start_dial(struct at_state_t *at_state, void *data, int seq_index) at_state->pending_commands |= PC_CID; - dbg(DEBUG_CMD, "Scheduling PC_CID"); -//#ifdef GIG_MAYINITONDIAL -// if (atomic_read(&cs->MState) == MS_UNKNOWN) { -// cs->at_state.pending_commands |= PC_INIT; -// dbg(DEBUG_CMD, "Scheduling PC_INIT"); -// } -//#endif - atomic_set(&cs->commands_pending, 1); //FIXME + gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); + atomic_set(&cs->commands_pending, 1); return; error: at_state->pending_commands |= PC_NOCID; - dbg(DEBUG_CMD, "Scheduling PC_NOCID"); - atomic_set(&cs->commands_pending, 1); //FIXME + gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); + atomic_set(&cs->commands_pending, 1); return; } @@ -991,13 +972,13 @@ static void start_accept(struct at_state_t *at_state) if (retval == 0) { at_state->pending_commands |= PC_ACCEPT; - dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); - atomic_set(&cs->commands_pending, 1); //FIXME + gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); + atomic_set(&cs->commands_pending, 1); } else { //FIXME at_state->pending_commands |= PC_HUP; - dbg(DEBUG_CMD, "Scheduling PC_HUP"); - atomic_set(&cs->commands_pending, 1); //FIXME + gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); + atomic_set(&cs->commands_pending, 1); } } @@ -1008,9 +989,10 @@ static void do_start(struct cardstate *cs) if (atomic_read(&cs->mstate) != MS_LOCKED) schedule_init(cs, MS_INIT); + cs->isdn_up = 1; gigaset_i4l_cmd(cs, ISDN_STAT_RUN); - // FIXME: not in locked mode - // FIXME 2: only after init sequence + // FIXME: not in locked mode + // FIXME 2: only after init sequence cs->waiting = 0; wake_up(&cs->waitqueue); @@ -1023,6 +1005,12 @@ static void finish_shutdown(struct cardstate *cs) atomic_set(&cs->mode, M_UNKNOWN); } + /* Tell the LL that the device is not available .. */ + if (cs->isdn_up) { + cs->isdn_up = 0; + gigaset_i4l_cmd(cs, ISDN_STAT_STOP); + } + /* The rest is done by cleanup_cs () in user mode. */ cs->cmd_result = -ENODEV; @@ -1037,15 +1025,20 @@ static void do_shutdown(struct cardstate *cs) if (atomic_read(&cs->mstate) == MS_READY) { atomic_set(&cs->mstate, MS_SHUTDOWN); cs->at_state.pending_commands |= PC_SHUTDOWN; - atomic_set(&cs->commands_pending, 1); //FIXME - dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); //FIXME - //gigaset_schedule_event(cs); //FIXME + atomic_set(&cs->commands_pending, 1); + gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); } else finish_shutdown(cs); } static void do_stop(struct cardstate *cs) { + unsigned long flags; + + spin_lock_irqsave(&cs->lock, flags); + cs->connected = 0; + spin_unlock_irqrestore(&cs->lock, flags); + do_shutdown(cs); } @@ -1069,9 +1062,11 @@ static int reinit_and_retry(struct cardstate *cs, int channel) return 0; if (channel < 0) - warn("Could not enter cid mode. Reinit device and try again."); + dev_warn(cs->dev, + "Could not enter cid mode. Reinit device and try again.\n"); else { - warn("Could not get a call id. Reinit device and try again."); + dev_warn(cs->dev, + "Could not get a call id. Reinit device and try again.\n"); cs->bcs[channel].at_state.pending_commands |= PC_CID; } schedule_init(cs, MS_INIT); @@ -1079,7 +1074,7 @@ static int reinit_and_retry(struct cardstate *cs, int channel) } static int at_state_invalid(struct cardstate *cs, - struct at_state_t *test_ptr) + struct at_state_t *test_ptr) { unsigned long flags; unsigned channel; @@ -1116,7 +1111,7 @@ static void handle_icall(struct cardstate *cs, struct bc_state *bcs, case ICALL_ACCEPT: break; default: - err("internal error: disposition=%d", retval); + dev_err(cs->dev, "internal error: disposition=%d\n", retval); /* --v-- fall through --v-- */ case ICALL_IGNORE: case ICALL_REJECT: @@ -1160,7 +1155,6 @@ static int do_lock(struct cardstate *cs) mode = atomic_read(&cs->mode); atomic_set(&cs->mstate, MS_LOCKED); atomic_set(&cs->mode, M_UNKNOWN); - //FIXME reset card state / at states / bcs states return mode; } @@ -1173,8 +1167,7 @@ static int do_unlock(struct cardstate *cs) atomic_set(&cs->mstate, MS_UNINITIALIZED); atomic_set(&cs->mode, M_UNKNOWN); gigaset_free_channels(cs); - //FIXME reset card state / at states / bcs states - if (atomic_read(&cs->connected)) + if (cs->connected) schedule_init(cs, MS_INIT); return 0; @@ -1203,21 +1196,23 @@ static void do_action(int action, struct cardstate *cs, at_state->waiting = 1; break; case ACT_INIT: - //FIXME setup everything cs->at_state.pending_commands &= ~PC_INIT; cs->cur_at_seq = SEQ_NONE; atomic_set(&cs->mode, M_UNIMODEM); - if (!atomic_read(&cs->cidmode)) { + 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); break; } + spin_unlock_irqrestore(&cs->lock, flags); cs->at_state.pending_commands |= PC_CIDMODE; - atomic_set(&cs->commands_pending, 1); //FIXME - dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + atomic_set(&cs->commands_pending, 1); + gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); break; case ACT_FAILINIT: - warn("Could not initialize the device."); + dev_warn(cs->dev, "Could not initialize the device.\n"); cs->dle = 0; init_failed(cs, M_UNKNOWN); cs->cur_at_seq = SEQ_NONE; @@ -1273,8 +1268,8 @@ static void do_action(int action, struct cardstate *cs, /* get fresh AT state structure for new CID */ at_state2 = get_free_channel(cs, ev->parameter); if (!at_state2) { - warn("RING ignored: " - "could not allocate channel structure"); + dev_warn(cs->dev, + "RING ignored: could not allocate channel structure\n"); break; } @@ -1302,7 +1297,7 @@ static void do_action(int action, struct cardstate *cs, at_state = *p_at_state; break; case ACT_FAILSDOWN: - warn("Could not shut down the device."); + dev_warn(cs->dev, "Could not shut down the device.\n"); /* fall through */ case ACT_FAKESDOWN: case ACT_SDOWN: @@ -1355,7 +1350,7 @@ static void do_action(int action, struct cardstate *cs, break; case ACT_ABORTHUP: cs->cur_at_seq = SEQ_NONE; - warn("Could not hang up."); + dev_warn(cs->dev, "Could not hang up.\n"); at_state->cid = -1; if (bcs && cs->onechannel) at_state->pending_commands |= PC_DLE0; @@ -1367,14 +1362,15 @@ static void do_action(int action, struct cardstate *cs, break; case ACT_FAILDLE0: cs->cur_at_seq = SEQ_NONE; - warn("Could not leave DLE mode."); + dev_warn(cs->dev, "Could not leave DLE mode.\n"); at_state2 = &cs->bcs[cs->curchannel].at_state; disconnect(&at_state2); schedule_init(cs, MS_RECOVER); break; case ACT_FAILDLE1: cs->cur_at_seq = SEQ_NONE; - warn("Could not enter DLE mode. Try to hang up."); + dev_warn(cs->dev, + "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); @@ -1395,7 +1391,8 @@ static void do_action(int action, struct cardstate *cs, cs->cur_at_seq = SEQ_NONE; channel = cs->curchannel; if (!reinit_and_retry(cs, channel)) { - warn("Could not get a call id. Dialing not possible"); + dev_warn(cs->dev, + "Could not get a call ID. Cannot dial.\n"); at_state2 = &cs->bcs[channel].at_state; disconnect(&at_state2); } @@ -1428,7 +1425,8 @@ static void do_action(int action, struct cardstate *cs, at_state->pending_commands |= PC_HUP; atomic_set(&cs->commands_pending, 1); break; - case ACT_GETSTRING: /* warning: RING, ZDLE, ... are not handled properly any more */ + case ACT_GETSTRING: /* warning: RING, ZDLE, ... + are not handled properly anymore */ at_state->getstring = 1; break; case ACT_SETVER: @@ -1469,16 +1467,16 @@ static void do_action(int action, struct cardstate *cs, case ACT_GOTVER: if (cs->gotfwver == 0) { cs->gotfwver = 1; - dbg(DEBUG_ANY, - "firmware version %02d.%03d.%02d.%02d", - cs->fwver[0], cs->fwver[1], - cs->fwver[2], cs->fwver[3]); + gig_dbg(DEBUG_ANY, + "firmware version %02d.%03d.%02d.%02d", + cs->fwver[0], cs->fwver[1], + cs->fwver[2], cs->fwver[3]); break; } /* fall through */ case ACT_FAILVER: cs->gotfwver = -1; - err("could not read firmware version."); + dev_err(cs->dev, "could not read firmware version.\n"); break; #ifdef CONFIG_GIGASET_DEBUG case ACT_ERROR: @@ -1496,16 +1494,16 @@ static void do_action(int action, struct cardstate *cs, break; #endif case ACT_DEBUG: - dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", + gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", __func__, ev->type, at_state->ConState); break; case ACT_WARN: - warn("%s: resp_code %d in ConState %d!", - __func__, ev->type, at_state->ConState); + dev_warn(cs->dev, "%s: resp_code %d in ConState %d!\n", + __func__, ev->type, at_state->ConState); break; case ACT_ZCAU: - warn("cause code %04x in connection state %d.", - ev->parameter, at_state->ConState); + dev_warn(cs->dev, "cause code %04x in connection state %d.\n", + ev->parameter, at_state->ConState); break; /* events from the LL */ @@ -1516,14 +1514,14 @@ static void do_action(int action, struct cardstate *cs, start_accept(at_state); break; case ACT_PROTO_L2: - dbg(DEBUG_CMD, - "set protocol to %u", (unsigned) ev->parameter); + gig_dbg(DEBUG_CMD, "set protocol to %u", + (unsigned) ev->parameter); at_state->bcs->proto2 = ev->parameter; break; case ACT_HUP: at_state->pending_commands |= PC_HUP; - atomic_set(&cs->commands_pending, 1); //FIXME - dbg(DEBUG_CMD, "Scheduling PC_HUP"); + atomic_set(&cs->commands_pending, 1); + gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); break; /* hotplug events */ @@ -1555,17 +1553,19 @@ static void do_action(int action, struct cardstate *cs, /* events from the proc file system */ // FIXME without ACT_xxxx? case ACT_PROC_CIDMODE: - if (ev->parameter != atomic_read(&cs->cidmode)) { - atomic_set(&cs->cidmode, ev->parameter); + spin_lock_irqsave(&cs->lock, flags); + if (ev->parameter != cs->cidmode) { + cs->cidmode = ev->parameter; if (ev->parameter) { cs->at_state.pending_commands |= PC_CIDMODE; - dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); } else { cs->at_state.pending_commands |= PC_UMMODE; - dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); + gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); } atomic_set(&cs->commands_pending, 1); } + spin_unlock_irqrestore(&cs->lock, flags); cs->waiting = 0; wake_up(&cs->waitqueue); break; @@ -1590,7 +1590,7 @@ static void do_action(int action, struct cardstate *cs, *p_resp_code = RSP_NULL; } } else - err("%s: action==%d!", __func__, action); + dev_err(cs->dev, "%s: action==%d!\n", __func__, action); } } @@ -1609,47 +1609,46 @@ static void process_event(struct cardstate *cs, struct event_t *ev) int curact; unsigned long flags; - IFNULLRET(cs); - IFNULLRET(ev); - if (ev->cid >= 0) { at_state = at_state_from_cid(cs, ev->cid); if (!at_state) { gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, - NULL, 0, NULL); + NULL, 0, NULL); return; } } else { at_state = ev->at_state; if (at_state_invalid(cs, at_state)) { - dbg(DEBUG_ANY, - "event for invalid at_state %p", at_state); + gig_dbg(DEBUG_ANY, "event for invalid at_state %p", + at_state); return; } } - dbg(DEBUG_CMD, - "connection state %d, event %d", at_state->ConState, ev->type); + gig_dbg(DEBUG_CMD, "connection state %d, event %d", + at_state->ConState, ev->type); bcs = at_state->bcs; sendcid = at_state->cid; /* Setting the pointer to the dial array */ rep = at_state->replystruct; - IFNULLRET(rep); + spin_lock_irqsave(&cs->lock, flags); if (ev->type == EV_TIMEOUT) { - if (ev->parameter != atomic_read(&at_state->timer_index) + if (ev->parameter != at_state->timer_index || !at_state->timer_active) { ev->type = RSP_NONE; /* old timeout */ - dbg(DEBUG_ANY, "old timeout"); + gig_dbg(DEBUG_ANY, "old timeout"); } else if (!at_state->waiting) - dbg(DEBUG_ANY, "timeout occured"); + gig_dbg(DEBUG_ANY, "timeout occurred"); else - dbg(DEBUG_ANY, "stopped waiting"); + gig_dbg(DEBUG_ANY, "stopped waiting"); } + spin_unlock_irqrestore(&cs->lock, flags); - /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] or at_state->str_var[STR_XXXX], set it */ + /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] + or at_state->str_var[STR_XXXX], set it */ if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) { index = ev->type - RSP_VAR; at_state->int_var[index] = ev->parameter; @@ -1657,20 +1656,22 @@ static void process_event(struct cardstate *cs, struct event_t *ev) index = ev->type - RSP_STR; kfree(at_state->str_var[index]); at_state->str_var[index] = ev->ptr; - ev->ptr = NULL; /* prevent process_events() from deallocating ptr */ + ev->ptr = NULL; /* prevent process_events() from + deallocating ptr */ } if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING) at_state->getstring = 0; - /* Search row in dial array which matches modem response and current constate */ + /* Search row in dial array which matches modem response and current + constate */ for (;; rep++) { rcode = rep->resp_code; - /* dbg (DEBUG_ANY, "rcode %d", rcode); */ if (rcode == RSP_LAST) { /* found nothing...*/ - warn("%s: rcode=RSP_LAST: resp_code %d in ConState %d!", - __func__, ev->type, at_state->ConState); + dev_warn(cs->dev, "%s: rcode=RSP_LAST: " + "resp_code %d in ConState %d!\n", + __func__, ev->type, at_state->ConState); return; } if ((rcode == RSP_ANY || rcode == ev->type) @@ -1706,14 +1707,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev) } else { /* Send command to modem if not NULL... */ if (p_command/*rep->command*/) { - if (atomic_read(&cs->connected)) + if (cs->connected) send_command(cs, p_command, - sendcid, cs->dle, - GFP_ATOMIC); + sendcid, cs->dle, + GFP_ATOMIC); else gigaset_add_event(cs, at_state, - RSP_NODEV, - NULL, 0, NULL); + RSP_NODEV, + NULL, 0, NULL); } spin_lock_irqsave(&cs->lock, flags); @@ -1723,8 +1724,7 @@ static void process_event(struct cardstate *cs, struct event_t *ev) } else if (rep->timeout > 0) { /* new timeout */ at_state->timer_expires = rep->timeout * 10; at_state->timer_active = 1; - new_index(&at_state->timer_index, - MAX_TIMER_INDEX); + ++at_state->timer_index; } spin_unlock_irqrestore(&cs->lock, flags); } @@ -1744,17 +1744,16 @@ static void process_command_flags(struct cardstate *cs) struct bc_state *bcs; int i; int sequence; - - IFNULLRET(cs); + unsigned long flags; atomic_set(&cs->commands_pending, 0); if (cs->cur_at_seq) { - dbg(DEBUG_CMD, "not searching scheduled commands: busy"); + gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); return; } - dbg(DEBUG_CMD, "searching scheduled commands"); + gig_dbg(DEBUG_CMD, "searching scheduled commands"); sequence = SEQ_NONE; @@ -1795,8 +1794,9 @@ static void process_command_flags(struct cardstate *cs) } /* only switch back to unimodem mode, if no commands are pending and no channels are up */ + spin_lock_irqsave(&cs->lock, flags); if (cs->at_state.pending_commands == PC_UMMODE - && !atomic_read(&cs->cidmode) + && !cs->cidmode && list_empty(&cs->temp_at_states) && atomic_read(&cs->mode) == M_CID) { sequence = SEQ_UMMODE; @@ -1810,6 +1810,7 @@ static void process_command_flags(struct cardstate *cs) } } } + spin_unlock_irqrestore(&cs->lock, flags); cs->at_state.pending_commands &= ~PC_UMMODE; if (sequence != SEQ_NONE) { schedule_sequence(cs, at_state, sequence); @@ -1865,11 +1866,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 0 - cs->retry_count = 2; -#else cs->retry_count = 1; -#endif schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); return; } @@ -1897,7 +1894,7 @@ static void process_command_flags(struct cardstate *cs) switch (atomic_read(&cs->mode)) { case M_UNIMODEM: cs->at_state.pending_commands |= PC_CIDMODE; - dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); atomic_set(&cs->commands_pending, 1); return; #ifdef GIG_MAYINITONDIAL @@ -1926,18 +1923,21 @@ static void process_events(struct cardstate *cs) int i; int check_flags = 0; int was_busy; + unsigned long flags; - /* no locking needed (only one reader) */ - head = atomic_read(&cs->ev_head); + spin_lock_irqsave(&cs->ev_lock, flags); + head = cs->ev_head; for (i = 0; i < 2 * MAX_EVENTS; ++i) { - tail = atomic_read(&cs->ev_tail); + tail = cs->ev_tail; if (tail == head) { if (!check_flags && !atomic_read(&cs->commands_pending)) break; check_flags = 0; + spin_unlock_irqrestore(&cs->ev_lock, flags); process_command_flags(cs); - tail = atomic_read(&cs->ev_tail); + spin_lock_irqsave(&cs->ev_lock, flags); + tail = cs->ev_tail; if (tail == head) { if (!atomic_read(&cs->commands_pending)) break; @@ -1947,18 +1947,23 @@ static void process_events(struct cardstate *cs) ev = cs->events + head; was_busy = cs->cur_at_seq != SEQ_NONE; + spin_unlock_irqrestore(&cs->ev_lock, flags); process_event(cs, ev); + spin_lock_irqsave(&cs->ev_lock, flags); kfree(ev->ptr); ev->ptr = NULL; if (was_busy && cs->cur_at_seq == SEQ_NONE) check_flags = 1; head = (head + 1) % MAX_EVENTS; - atomic_set(&cs->ev_head, head); + cs->ev_head = head; } + spin_unlock_irqrestore(&cs->ev_lock, flags); + if (i == 2 * MAX_EVENTS) { - err("infinite loop in process_events; aborting."); + dev_err(cs->dev, + "infinite loop in process_events; aborting.\n"); } } @@ -1970,12 +1975,9 @@ void gigaset_handle_event(unsigned long data) { struct cardstate *cs = (struct cardstate *) data; - IFNULLRET(cs); - IFNULLRET(cs->inbuf); - /* handle incoming data on control/common channel */ if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) { - dbg(DEBUG_INTR, "processing new data"); + 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 729edcd..22b9693 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -1,11 +1,16 @@ -/* Siemens Gigaset 307x driver +/* + * Siemens Gigaset 307x driver * Common header file for all connection variants * - * Written by Stefan Eilers <Eilers.Stefan@epost.de> + * Written by Stefan Eilers * and Hansjoerg Lipp <hjlipp@web.de> * - * Version: $Id: gigaset.h,v 1.97.4.26 2006/02/04 18:28:16 hjlipp Exp $ - * =========================================================================== + * ===================================================================== + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * ===================================================================== */ #ifndef GIGASET_H @@ -15,7 +20,6 @@ #include <linux/kernel.h> #include <linux/compiler.h> #include <linux/types.h> -#include <asm/atomic.h> #include <linux/spinlock.h> #include <linux/isdnif.h> #include <linux/usb.h> @@ -27,21 +31,22 @@ #include <linux/tty.h> #include <linux/tty_driver.h> #include <linux/list.h> +#include <asm/atomic.h> #define GIG_VERSION {0,5,0,0} #define GIG_COMPAT {0,4,0,0} -#define MAX_REC_PARAMS 10 /* Max. number of params in response string */ -#define MAX_RESP_SIZE 512 /* Max. size of a response string */ -#define HW_HDR_LEN 2 /* Header size used to store ack info */ +#define MAX_REC_PARAMS 10 /* Max. number of params in response string */ +#define MAX_RESP_SIZE 512 /* Max. size of a response string */ +#define HW_HDR_LEN 2 /* Header size used to store ack info */ -#define MAX_EVENTS 64 /* size of event queue */ +#define MAX_EVENTS 64 /* size of event queue */ #define RBUFSIZE 8192 -#define SBUFSIZE 4096 /* sk_buff payload size */ +#define SBUFSIZE 4096 /* sk_buff payload size */ -#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */ -#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */ +#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */ +#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */ /* compile time options */ #define GIG_MAJOR 0 @@ -50,10 +55,7 @@ #define GIG_RETRYCID #define GIG_X75 -#define MAX_TIMER_INDEX 1000 -#define MAX_SEQ_INDEX 1000 - -#define GIG_TICK (HZ / 10) +#define GIG_TICK 100 /* in milliseconds */ /* timeout values (unit: 1 sec) */ #define INIT_TIMEOUT 1 @@ -67,74 +69,89 @@ #define MAXACT 3 -#define IFNULL(a) if (unlikely(!(a))) -#define IFNULLRET(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return; } -#define IFNULLRETVAL(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return (b); } -#define IFNULLCONT(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); continue; } -#define IFNULLGOTO(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); goto b; } - 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. */ -enum debuglevel { /* up to 24 bits (atomic_t) */ +/* 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. + */ +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_DUMP = 0x0010, /* Activating hexdump debug output on + interrupt requests, not available as + run-time option */ 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 output interrupt processing */ + 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 */ - DEBUG_TRANSCMD = 0x02000, /*AT-COMMANDS+RESPONSES*/ - DEBUG_MCMD = 0x04000, /*COMMANDS THAT ARE SENT VERY OFTEN*/ - DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data structures */ + DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */ + DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ + DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data + structures */ DEBUG_LOCK = 0x10000, /* semaphore operations */ DEBUG_OUTPUT = 0x20000, /* output to device */ - DEBUG_ISO = 0x40000, /* isochronous transfers */ + DEBUG_ISO = 0x40000, /* isochronous transfers */ DEBUG_IF = 0x80000, /* character device operations */ - DEBUG_USBREQ = 0x100000, /* USB communication (except payload data) */ - DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when MS_LOCKED */ + DEBUG_USBREQ = 0x100000, /* USB communication (except payload + data) */ + DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when + MS_LOCKED */ - DEBUG_ANY = 0x3fffff, /* print message if any of the others is activated */ + DEBUG_ANY = 0x3fffff, /* print message if any of the others is + activated */ }; -#ifdef CONFIG_GIGASET_DEBUG -#define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) -//#define DEBUG_DEFAULT (DEBUG_LOCK | DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUF_IF | DEBUG_DRIVER | DEBUG_OUTPUT | DEBUG_INTR) -#else -#define DEBUG_DEFAULT 0 +/* missing from linux/device.h ... */ +#ifndef dev_notice +#define dev_notice(dev, format, arg...) \ + dev_printk(KERN_NOTICE , dev , format , ## arg) #endif -/* redefine syslog macros to prepend module name instead of entire source path */ -/* The space before the comma in ", ##" is needed by gcc 2.95 */ +/* Kernel message macros for situations where dev_printk and friends cannot be + * used for lack of reliable access to a device structure. + * linux/usb.h already contains these but in an obsolete form which clutters + * the log needlessly, and according to the USB maintainer those should be + * removed rather than fixed anyway. + */ +#undef err #undef info -#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) - -#undef notice -#define notice(format, arg...) printk(KERN_NOTICE "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) - #undef warn -#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) +#undef notice -#undef err -#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) +#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \ + format "\n" , ## arg) +#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \ + format "\n" , ## arg) +#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \ + format "\n" , ## arg) +#define notice(format, arg...) printk(KERN_NOTICE KBUILD_MODNAME ": " \ + format "\n" , ## arg) -#undef dbg #ifdef CONFIG_GIGASET_DEBUG -#define dbg(level, format, arg...) do { if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \ - printk(KERN_DEBUG "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg); } while (0) + +#define gig_dbg(level, format, arg...) \ + do { \ + if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \ + printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \ + ## arg); \ + } while (0) +#define DEBUG_DEFAULT (DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) + #else -#define dbg(level, format, arg...) do {} while (0) + +#define gig_dbg(level, format, arg...) do {} while (0) +#define DEBUG_DEFAULT 0 + #endif void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, - size_t len, const unsigned char *buf, int from_user); + size_t len, const unsigned char *buf); /* connection state */ #define ZSAU_NONE 0 @@ -148,13 +165,14 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define ZSAU_UNKNOWN -1 /* USB control transfer requests */ -#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) -#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) +#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) +#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) /* int-in-events 3070 */ #define HD_B1_FLOW_CONTROL 0x80 #define HD_B2_FLOW_CONTROL 0x81 -#define HD_RECEIVEATDATA_ACK (0x35) // 3070 // att: HD_RECEIVE>>AT<<DATA_ACK +#define HD_RECEIVEATDATA_ACK (0x35) // 3070 + // att: HD_RECEIVE>>AT<<DATA_ACK #define HD_READY_SEND_ATDATA (0x36) // 3070 #define HD_OPEN_ATCHANNEL_ACK (0x37) // 3070 #define HD_CLOSE_ATCHANNEL_ACK (0x38) // 3070 @@ -181,17 +199,18 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define HD_CLOSE_ATCHANNEL (0x29) // 3070 /* USB frames for isochronous transfer */ -#define BAS_FRAMETIME 1 /* number of milliseconds between frames */ -#define BAS_NUMFRAMES 8 /* number of frames per URB */ -#define BAS_MAXFRAME 16 /* allocated bytes per frame */ -#define BAS_NORMFRAME 8 /* send size without flow control */ -#define BAS_HIGHFRAME 10 /* " " with positive flow control */ -#define BAS_LOWFRAME 5 /* " " with negative flow control */ -#define BAS_CORRFRAMES 4 /* flow control multiplicator */ - -#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isochronous input buffer per URB */ -#define BAS_OUTBUFSIZE 4096 /* size of common isochronous output buffer */ -#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isochronous output buffer */ +#define BAS_FRAMETIME 1 /* number of milliseconds between frames */ +#define BAS_NUMFRAMES 8 /* number of frames per URB */ +#define BAS_MAXFRAME 16 /* allocated bytes per frame */ +#define BAS_NORMFRAME 8 /* send size without flow control */ +#define BAS_HIGHFRAME 10 /* " " with positive flow control */ +#define BAS_LOWFRAME 5 /* " " with negative flow control */ +#define BAS_CORRFRAMES 4 /* flow control multiplicator */ + +#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) + /* size of isoc in buf per URB */ +#define BAS_OUTBUFSIZE 4096 /* size of common isoc out buffer */ +#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isoc out buf */ #define BAS_INURBS 3 #define BAS_OUTURBS 3 @@ -207,40 +226,40 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define AT_NUM 7 /* variables in struct at_state_t */ -#define VAR_ZSAU 0 -#define VAR_ZDLE 1 -#define VAR_ZVLS 2 -#define VAR_ZCTP 3 -#define VAR_NUM 4 - -#define STR_NMBR 0 -#define STR_ZCPN 1 -#define STR_ZCON 2 -#define STR_ZBC 3 -#define STR_ZHLC 4 -#define STR_NUM 5 - -#define EV_TIMEOUT -105 -#define EV_IF_VER -106 -#define EV_PROC_CIDMODE -107 -#define EV_SHUTDOWN -108 -#define EV_START -110 -#define EV_STOP -111 -#define EV_IF_LOCK -112 -#define EV_PROTO_L2 -113 -#define EV_ACCEPT -114 -#define EV_DIAL -115 -#define EV_HUP -116 -#define EV_BC_OPEN -117 -#define EV_BC_CLOSED -118 +#define VAR_ZSAU 0 +#define VAR_ZDLE 1 +#define VAR_ZVLS 2 +#define VAR_ZCTP 3 +#define VAR_NUM 4 + +#define STR_NMBR 0 +#define STR_ZCPN 1 +#define STR_ZCON 2 +#define STR_ZBC 3 +#define STR_ZHLC 4 +#define STR_NUM 5 + +#define EV_TIMEOUT -105 +#define EV_IF_VER -106 +#define EV_PROC_CIDMODE -107 +#define EV_SHUTDOWN -108 +#define EV_START -110 +#define EV_STOP -111 +#define EV_IF_LOCK -112 +#define EV_PROTO_L2 -113 +#define EV_ACCEPT -114 +#define EV_DIAL -115 +#define EV_HUP -116 +#define EV_BC_OPEN -117 +#define EV_BC_CLOSED -118 /* input state */ -#define INS_command 0x0001 -#define INS_DLE_char 0x0002 -#define INS_byte_stuff 0x0004 -#define INS_have_data 0x0008 -#define INS_skip_frame 0x0010 -#define INS_DLE_command 0x0020 +#define INS_command 0x0001 +#define INS_DLE_char 0x0002 +#define INS_byte_stuff 0x0004 +#define INS_have_data 0x0008 +#define INS_skip_frame 0x0010 +#define INS_DLE_command 0x0020 #define INS_flag_hunt 0x0040 /* channel state */ @@ -248,27 +267,27 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define CHS_B_UP 0x02 #define CHS_NOTIFY_LL 0x04 -#define ICALL_REJECT 0 -#define ICALL_ACCEPT 1 -#define ICALL_IGNORE 2 +#define ICALL_REJECT 0 +#define ICALL_ACCEPT 1 +#define ICALL_IGNORE 2 /* device state */ -#define MS_UNINITIALIZED 0 -#define MS_INIT 1 -#define MS_LOCKED 2 -#define MS_SHUTDOWN 3 -#define MS_RECOVER 4 -#define MS_READY 5 +#define MS_UNINITIALIZED 0 +#define MS_INIT 1 +#define MS_LOCKED 2 +#define MS_SHUTDOWN 3 +#define MS_RECOVER 4 +#define MS_READY 5 /* mode */ -#define M_UNKNOWN 0 -#define M_CONFIG 1 -#define M_UNIMODEM 2 -#define M_CID 3 +#define M_UNKNOWN 0 +#define M_CONFIG 1 +#define M_UNIMODEM 2 +#define M_CID 3 /* start mode */ -#define SM_LOCKED 0 -#define SM_ISDN 1 /* default */ +#define SM_LOCKED 0 +#define SM_ISDN 1 /* default */ struct gigaset_ops; struct gigaset_driver; @@ -283,27 +302,26 @@ struct ser_bc_state; struct bas_bc_state; struct reply_t { - int resp_code; /* RSP_XXXX */ - int min_ConState; /* <0 => ignore */ - int max_ConState; /* <0 => ignore */ - int parameter; /* e.g. ZSAU_XXXX <0: ignore*/ - int new_ConState; /* <0 => ignore */ - int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/ - int action[MAXACT]; /* ACT_XXXX */ - char *command; /* NULL==none */ + int resp_code; /* RSP_XXXX */ + int min_ConState; /* <0 => ignore */ + int max_ConState; /* <0 => ignore */ + int parameter; /* e.g. ZSAU_XXXX <0: ignore*/ + int new_ConState; /* <0 => ignore */ + int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/ + int action[MAXACT]; /* ACT_XXXX */ + char *command; /* NULL==none */ }; extern struct reply_t gigaset_tab_cid_m10x[]; extern struct reply_t gigaset_tab_nocid_m10x[]; struct inbuf_t { - unsigned char *rcvbuf; /* usb-gigaset receive buffer */ + unsigned char *rcvbuf; /* usb-gigaset receive buffer */ struct bc_state *bcs; - struct cardstate *cs; - int inputstate; - - atomic_t head, tail; - unsigned char data[RBUFSIZE]; + struct cardstate *cs; + int inputstate; + atomic_t head, tail; + unsigned char data[RBUFSIZE]; }; /* isochronous write buffer structure @@ -319,16 +337,9 @@ struct inbuf_t { * if writesem <= 0, data[write..read-1] is currently being written to * - idle contains the byte value to repeat when the end of valid data is * reached; if nextread==write (buffer contains no data to send), either the - * BAS_OUTBUFPAD bytes immediately before data[write] (if write>=BAS_OUTBUFPAD) - * or those of the pad area (if write<BAS_OUTBUFPAD) are also filled with that - * value - * - optionally, the following statistics on the buffer's usage can be collected: - * maxfill: maximum number of bytes occupied - * idlefills: number of times a frame of idle bytes is prepared - * emptygets: number of times the buffer was empty when a data frame was requested - * backtoback: number of times two data packets were entered into the buffer - * without intervening idle flags - * nakedback: set if no idle flags have been inserted since the last data packet + * BAS_OUTBUFPAD bytes immediately before data[write] (if + * write>=BAS_OUTBUFPAD) or those of the pad area (if write<BAS_OUTBUFPAD) + * are also filled with that value */ struct isowbuf_t { atomic_t read; @@ -358,34 +369,28 @@ struct isow_urbctx_t { * it is currently assigned a B channel */ struct at_state_t { - struct list_head list; - int waiting; - int getstring; - atomic_t timer_index; + struct list_head list; + int waiting; + int getstring; + unsigned timer_index; unsigned long timer_expires; int timer_active; - unsigned int ConState; /* State of connection */ - struct reply_t *replystruct; - int cid; - int int_var[VAR_NUM]; /* see VAR_XXXX */ - char *str_var[STR_NUM]; /* see STR_XXXX */ - unsigned pending_commands; /* see PC_XXXX */ - atomic_t seq_index; - - struct cardstate *cs; - struct bc_state *bcs; + unsigned int ConState; /* State of connection */ + struct reply_t *replystruct; + int cid; + int int_var[VAR_NUM]; /* see VAR_XXXX */ + char *str_var[STR_NUM]; /* see STR_XXXX */ + unsigned pending_commands; /* see PC_XXXX */ + unsigned seq_index; + + struct cardstate *cs; + struct bc_state *bcs; }; struct resp_type_t { unsigned char *response; - int resp_code; /* RSP_XXXX */ - int type; /* RT_XXXX */ -}; - -struct prot_skb { - atomic_t empty; - struct semaphore *sem; - struct sk_buff *skb; + int resp_code; /* RSP_XXXX */ + int type; /* RT_XXXX */ }; struct event_t { @@ -398,29 +403,29 @@ struct event_t { /* This buffer holds all information about the used B-Channel */ struct bc_state { - struct sk_buff *tx_skb; /* Current transfer buffer to modem */ - struct sk_buff_head squeue; /* B-Channel send Queue */ + struct sk_buff *tx_skb; /* Current transfer buffer to modem */ + struct sk_buff_head squeue; /* B-Channel send Queue */ /* Variables for debugging .. */ - int corrupted; /* Counter for corrupted packages */ - int trans_down; /* Counter of packages (downstream) */ - int trans_up; /* Counter of packages (upstream) */ + int corrupted; /* Counter for corrupted packages */ + int trans_down; /* Counter of packages (downstream) */ + int trans_up; /* Counter of packages (upstream) */ struct at_state_t at_state; unsigned long rcvbytes; __u16 fcs; struct sk_buff *skb; - int inputstate; /* see INS_XXXX */ + int inputstate; /* see INS_XXXX */ int channel; struct cardstate *cs; - unsigned chstate; /* bitmap (CHS_*) */ + unsigned chstate; /* bitmap (CHS_*) */ int ignore; - unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */ - char *commands[AT_NUM]; /* see AT_XXXX */ + unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */ + char *commands[AT_NUM]; /* see AT_XXXX */ #ifdef CONFIG_GIGASET_DEBUG int emptycount; @@ -428,37 +433,39 @@ struct bc_state { int busy; int use_count; - /* hardware drivers */ + /* private data of hardware drivers */ union { - struct ser_bc_state *ser; /* private data of serial hardware driver */ - struct usb_bc_state *usb; /* private data of usb hardware driver */ - struct bas_bc_state *bas; + struct ser_bc_state *ser; /* serial hardware driver */ + struct usb_bc_state *usb; /* usb hardware driver (m105) */ + struct bas_bc_state *bas; /* usb hardware driver (base) */ } hw; }; struct cardstate { struct gigaset_driver *driver; unsigned minor_index; + struct device *dev; const struct gigaset_ops *ops; /* Stuff to handle communication */ - //wait_queue_head_t initwait; wait_queue_head_t waitqueue; int waiting; - atomic_t mode; /* see M_XXXX */ - atomic_t mstate; /* Modem state: see MS_XXXX */ - /* only changed by the event layer */ + atomic_t mode; /* see M_XXXX */ + atomic_t mstate; /* Modem state: see MS_XXXX */ + /* only changed by the event layer */ int cmd_result; int channels; - struct bc_state *bcs; /* Array of struct bc_state */ + struct bc_state *bcs; /* Array of struct bc_state */ - int onechannel; /* data and commands transmitted in one stream (M10x) */ + int onechannel; /* data and commands transmitted in one + stream (M10x) */ spinlock_t lock; - struct at_state_t at_state; /* at_state_t for cid == 0 */ - struct list_head temp_at_states; /* list of temporary "struct at_state_t"s without B channel */ + struct at_state_t at_state; /* at_state_t for cid == 0 */ + struct list_head temp_at_states;/* list of temporary "struct + at_state_t"s without B channel */ struct inbuf_t *inbuf; @@ -474,58 +481,69 @@ struct cardstate { unsigned fwver[4]; int gotfwver; - atomic_t running; /* !=0 if events are handled */ - atomic_t connected; /* !=0 if hardware is connected */ + unsigned running; /* !=0 if events are handled */ + unsigned connected; /* !=0 if hardware is connected */ + unsigned isdn_up; /* !=0 after ISDN_STAT_RUN */ - atomic_t cidmode; + unsigned cidmode; - int myid; /* id for communication with LL */ + int myid; /* id for communication with LL */ isdn_if iif; struct reply_t *tabnocid; struct reply_t *tabcid; int cs_init; - int ignoreframes; /* frames to ignore after setting up the B channel */ - struct semaphore sem; /* locks this structure: */ - /* connected is not changed, */ - /* hardware_up is not changed, */ - /* MState is not changed to or from MS_LOCKED */ + int ignoreframes; /* frames to ignore after setting up the + B channel */ + struct mutex mutex; /* locks this structure: + * connected is not changed, + * hardware_up is not changed, + * MState is not changed to or from + * MS_LOCKED */ struct timer_list timer; int retry_count; - int dle; /* !=0 if modem commands/responses are dle encoded */ - int cur_at_seq; /* sequence of AT commands being processed */ - int curchannel; /* channel, those commands are meant for */ - atomic_t commands_pending; /* flag(s) in xxx.commands_pending have been set */ - struct tasklet_struct event_tasklet; /* tasklet for serializing AT commands. Scheduled - * -> for modem reponses (and incomming data for M10x) - * -> on timeout - * -> after setting bits in xxx.at_state.pending_command - * (e.g. command from LL) */ - struct tasklet_struct write_tasklet; /* tasklet for serial output - * (not used in base driver) */ + int dle; /* !=0 if modem commands/responses are + dle encoded */ + int cur_at_seq; /* sequence of AT commands being + processed */ + int curchannel; /* channel those commands are meant + for */ + atomic_t commands_pending; /* flag(s) in xxx.commands_pending have + been set */ + struct tasklet_struct event_tasklet; + /* tasklet for serializing AT commands. + * Scheduled + * -> for modem reponses (and + * incoming data for M10x) + * -> on timeout + * -> after setting bits in + * xxx.at_state.pending_command + * (e.g. command from LL) */ + struct tasklet_struct write_tasklet; + /* tasklet for serial output + * (not used in base driver) */ /* event queue */ struct event_t events[MAX_EVENTS]; - atomic_t ev_tail, ev_head; + unsigned ev_tail, ev_head; spinlock_t ev_lock; /* current modem response */ unsigned char respdata[MAX_RESP_SIZE]; unsigned cbytes; - /* hardware drivers */ + /* private data of hardware drivers */ union { - struct usb_cardstate *usb; /* private data of USB hardware driver */ - struct ser_cardstate *ser; /* private data of serial hardware driver */ - struct bas_cardstate *bas; /* private data of base hardware driver */ + struct usb_cardstate *usb; /* USB hardware driver (m105) */ + struct ser_cardstate *ser; /* serial hardware driver */ + struct bas_cardstate *bas; /* USB hardware driver (base) */ } hw; }; struct gigaset_driver { struct list_head list; - spinlock_t lock; /* locks minor tables and blocked */ - //struct semaphore sem; /* locks this structure */ + spinlock_t lock; /* locks minor tables and blocked */ struct tty_driver *tty; unsigned have_tty; unsigned minor; @@ -553,37 +571,42 @@ struct bas_bc_state { struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; struct isow_urbctx_t *isooutdone, *isooutfree, *isooutovfl; struct isowbuf_t *isooutbuf; - unsigned numsub; /* submitted URB counter (for diagnostic messages only) */ + unsigned numsub; /* submitted URB counter + (for diagnostic messages only) */ struct tasklet_struct sent_tasklet; /* isochronous input state */ spinlock_t isoinlock; struct urb *isoinurbs[BAS_INURBS]; unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; - struct urb *isoindone; /* completed isoc read URB */ - int loststatus; /* status of dropped URB */ - unsigned isoinlost; /* number of bytes lost */ - /* state of bit unstuffing algorithm (in addition to BC_state.inputstate) */ - unsigned seqlen; /* number of '1' bits not yet unstuffed */ - unsigned inbyte, inbits; /* collected bits for next byte */ + struct urb *isoindone; /* completed isoc read URB */ + int loststatus; /* status of dropped URB */ + unsigned isoinlost; /* number of bytes lost */ + /* state of bit unstuffing algorithm + (in addition to BC_state.inputstate) */ + unsigned seqlen; /* number of '1' bits not yet + unstuffed */ + unsigned inbyte, inbits; /* collected bits for next byte */ /* statistics */ - unsigned goodbytes; /* bytes correctly received */ - unsigned alignerrs; /* frames with incomplete byte at end */ - unsigned fcserrs; /* FCS errors */ - unsigned frameerrs; /* framing errors */ - unsigned giants; /* long frames */ - unsigned runts; /* short frames */ - unsigned aborts; /* HDLC aborts */ - unsigned shared0s; /* '0' bits shared between flags */ - unsigned stolen0s; /* '0' stuff bits also serving as leading flag bits */ + unsigned goodbytes; /* bytes correctly received */ + unsigned alignerrs; /* frames with incomplete byte at end */ + unsigned fcserrs; /* FCS errors */ + unsigned frameerrs; /* framing errors */ + unsigned giants; /* long frames */ + unsigned runts; /* short frames */ + unsigned aborts; /* HDLC aborts */ + unsigned shared0s; /* '0' bits shared between flags */ + unsigned stolen0s; /* '0' stuff bits also serving as + leading flag bits */ struct tasklet_struct rcvd_tasklet; }; struct gigaset_ops { - /* Called from ev-layer.c/interface.c for sending AT commands to the device */ + /* Called from ev-layer.c/interface.c for sending AT commands to the + device */ int (*write_cmd)(struct cardstate *cs, - const unsigned char *buf, int len, - struct tasklet_struct *wake_tasklet); + const unsigned char *buf, int len, + struct tasklet_struct *wake_tasklet); /* Called from interface.c for additional device control */ int (*write_room)(struct cardstate *cs); @@ -604,7 +627,7 @@ struct gigaset_ops { /* Called by gigaset_freecs() for freeing bcs->hw.xxx */ int (*freebcshw)(struct bc_state *bcs); - /* Called by gigaset_stop() or gigaset_bchannel_down() for resetting bcs->hw.xxx */ + /* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */ void (*reinitbcshw)(struct bc_state *bcs); /* Called by gigaset_initcs() for setting up cs->hw.xxx */ @@ -613,13 +636,10 @@ struct gigaset_ops { /* Called by gigaset_freecs() for freeing cs->hw.xxx */ void (*freecshw)(struct cardstate *cs); - ///* Called by gigaset_stop() for killing URBs, shutting down the device, ... - // hardwareup: ==0: don't try to shut down the device, hardware is really not accessible - // !=0: hardware still up */ - //void (*stophw)(struct cardstate *cs, int hardwareup); - - /* Called from common.c/interface.c for additional serial port control */ - int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, unsigned new_state); + /* Called from common.c/interface.c for additional serial port + control */ + int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, + unsigned new_state); int (*baud_rate)(struct cardstate *cs, unsigned cflag); int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); @@ -639,7 +659,7 @@ struct gigaset_ops { * <DLE_FLAG>: 0x10 * <EVENT>: ((a-z)* | (A-Z)* | (0-10)*)+ */ -#define DLE_FLAG 0x10 +#define DLE_FLAG 0x10 /* =========================================================================== * Functions implemented in asyncdata.c @@ -667,7 +687,8 @@ void gigaset_isoc_input(struct inbuf_t *inbuf); /* Called from bas-gigaset.c to process a block of data * received through the isochronous channel */ -void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs); +void gigaset_isoc_receive(unsigned char *src, unsigned count, + struct bc_state *bcs); /* Called from bas-gigaset.c to put a block of data * into the isochronous output buffer */ @@ -703,7 +724,7 @@ static inline void gigaset_isdn_rcv_err(struct bc_state *bcs) isdn_ctrl response; /* error -> LL */ - dbg(DEBUG_CMD, "sending L1ERR"); + gig_dbg(DEBUG_CMD, "sending L1ERR"); response.driver = bcs->cs->myid; response.command = ISDN_STAT_L1ERR; response.arg = bcs->channel; @@ -727,8 +748,8 @@ void gigaset_handle_modem_response(struct cardstate *cs); */ /* initialize sysfs for device */ -void gigaset_init_dev_sysfs(struct usb_interface *interface); -void gigaset_free_dev_sysfs(struct usb_interface *interface); +void gigaset_init_dev_sysfs(struct cardstate *cs); +void gigaset_free_dev_sysfs(struct cardstate *cs); /* =========================================================================== * Functions implemented in common.c/gigaset.h @@ -736,7 +757,7 @@ void gigaset_free_dev_sysfs(struct usb_interface *interface); void gigaset_bcs_reinit(struct bc_state *bcs); void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, - struct cardstate *cs, int cid); + struct cardstate *cs, int cid); int gigaset_get_channel(struct bc_state *bcs); void gigaset_free_channel(struct bc_state *bcs); int gigaset_get_channels(struct cardstate *cs); @@ -745,16 +766,15 @@ void gigaset_block_channels(struct cardstate *cs); /* Allocate and initialize driver structure. */ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, - const char *procname, - const char *devname, - const char *devfsname, - const struct gigaset_ops *ops, - struct module *owner); + const char *procname, + const char *devname, + const char *devfsname, + const struct gigaset_ops *ops, + struct module *owner); /* Deallocate driver structure. */ void gigaset_freedriver(struct gigaset_driver *drv); void gigaset_debugdrivers(void); -struct cardstate *gigaset_get_cs_by_minor(unsigned minor); struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); struct cardstate *gigaset_get_cs_by_id(int id); @@ -763,7 +783,8 @@ 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 gigaset_init[b]cs(). */ +/* Allocate and initialize card state. Calls hardware dependent + gigaset_init[b]cs(). */ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, int onechannel, int ignoreframes, int cidmode, const char *modulename); @@ -788,8 +809,8 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); * ptr must be kmalloc()ed (and not be freed by the caller). */ struct event_t *gigaset_add_event(struct cardstate *cs, - struct at_state_t *at_state, int type, - void *ptr, int parameter, void *arg); + struct at_state_t *at_state, int type, + void *ptr, int parameter, void *arg); /* Called on CONFIG1 command from frontend. */ int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode @@ -799,7 +820,7 @@ static inline void gigaset_schedule_event(struct cardstate *cs) { unsigned long flags; spin_lock_irqsave(&cs->lock, flags); - if (atomic_read(&cs->running)) + if (cs->running) tasklet_schedule(&cs->event_tasklet); spin_unlock_irqrestore(&cs->lock, flags); } @@ -810,7 +831,7 @@ static inline void gigaset_bchannel_down(struct bc_state *bcs) { gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL); - dbg(DEBUG_CMD, "scheduling BC_CLOSED"); + gig_dbg(DEBUG_CMD, "scheduling BC_CLOSED"); gigaset_schedule_event(bcs->cs); } @@ -820,36 +841,19 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs) { gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL); - dbg(DEBUG_CMD, "scheduling BC_OPEN"); + gig_dbg(DEBUG_CMD, "scheduling BC_OPEN"); gigaset_schedule_event(bcs->cs); } /* handling routines for sk_buff */ /* ============================= */ -/* private version of __skb_put() - * append 'len' bytes to the content of 'skb', already knowing that the - * existing buffer can accomodate them - * returns a pointer to the location where the new bytes should be copied to - * This function does not take any locks so it must be called with the - * appropriate locks held only. - */ -static inline unsigned char *gigaset_skb_put_quick(struct sk_buff *skb, - unsigned int len) -{ - unsigned char *tmp = skb->tail; - /*SKB_LINEAR_ASSERT(skb);*/ /* not needed here */ - skb->tail += len; - skb->len += len; - return tmp; -} - /* pass received skb to LL * Warning: skb must not be accessed anymore! */ static inline void gigaset_rcv_skb(struct sk_buff *skb, - struct cardstate *cs, - struct bc_state *bcs) + struct cardstate *cs, + struct bc_state *bcs) { cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb); bcs->trans_down++; @@ -859,8 +863,8 @@ static inline void gigaset_rcv_skb(struct sk_buff *skb, * Warning: skb must not be accessed anymore! */ static inline void gigaset_rcv_error(struct sk_buff *procskb, - struct cardstate *cs, - struct bc_state *bcs) + struct cardstate *cs, + struct bc_state *bcs) { if (procskb) dev_kfree_skb(procskb); @@ -877,46 +881,9 @@ static inline void gigaset_rcv_error(struct sk_buff *procskb, /* bitwise byte inversion table */ extern __u8 gigaset_invtab[]; /* in common.c */ - /* append received bytes to inbuf */ -static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf, - const unsigned char *src, - unsigned numbytes) -{ - unsigned n, head, tail, bytesleft; - - dbg(DEBUG_INTR, "received %u bytes", numbytes); - - if (!numbytes) - return 0; - - bytesleft = numbytes; - tail = atomic_read(&inbuf->tail); - head = atomic_read(&inbuf->head); - dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); - - while (bytesleft) { - if (head > tail) - n = head - 1 - tail; - else if (head == 0) - n = (RBUFSIZE-1) - tail; - else - n = RBUFSIZE - tail; - if (!n) { - err("buffer overflow (%u bytes lost)", bytesleft); - break; - } - if (n > bytesleft) - n = bytesleft; - memcpy(inbuf->data + tail, src, n); - bytesleft -= n; - tail = (tail + n) % RBUFSIZE; - src += n; - } - dbg(DEBUG_INTR, "setting tail to %u", tail); - atomic_set(&inbuf->tail, tail); - return numbytes != bytesleft; -} +int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, + unsigned numbytes); /* =========================================================================== * Functions implemented in interface.c @@ -924,7 +891,7 @@ static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf, /* initialize interface */ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, - const char *devname, const char *devfsname); + const char *devname, const char *devfsname); /* release interface */ void gigaset_if_freedriver(struct gigaset_driver *drv); /* add minor */ @@ -933,6 +900,6 @@ void gigaset_if_init(struct cardstate *cs); void gigaset_if_free(struct cardstate *cs); /* device received data */ void gigaset_if_receive(struct cardstate *cs, - unsigned char *buffer, size_t len); + unsigned char *buffer, size_t len); #endif diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 731a675..1654fa4 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -1,9 +1,9 @@ /* * Stuff used by all variants of the driver * - * Copyright (c) 2001 by Stefan Eilers (Eilers.Stefan@epost.de), - * Hansjoerg Lipp (hjlipp@web.de), - * Tilman Schmidt (tilman@imap.cc). + * Copyright (c) 2001 by Stefan Eilers, + * Hansjoerg Lipp <hjlipp@web.de>, + * Tilman Schmidt <tilman@imap.cc>. * * ===================================================================== * This program is free software; you can redistribute it and/or @@ -11,15 +11,11 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: i4l.c,v 1.3.2.9 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" -/* == Handling of I4L IO ============================================================================*/ +/* == Handling of I4L IO =====================================================*/ /* writebuf_from_LL * called by LL to transmit data on an open channel @@ -29,14 +25,16 @@ * parameters: * driverID driver ID as assigned by LL * channel channel number - * ack if != 0 LL wants to be notified on completion via statcallb(ISDN_STAT_BSENT) + * ack if != 0 LL wants to be notified on completion via + * statcallb(ISDN_STAT_BSENT) * skb skb containing data to send * return value: * number of accepted bytes * 0 if temporarily unable to accept data (out of buffer space) * <0 on error (eg. -EINVAL) */ -static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *skb) +static int writebuf_from_LL(int driverID, int channel, int ack, + struct sk_buff *skb) { struct cardstate *cs; struct bc_state *bcs; @@ -54,28 +52,25 @@ static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff * bcs = &cs->bcs[channel]; len = skb->len; - dbg(DEBUG_LLDATA, - "Receiving data from LL (id: %d, channel: %d, ack: %d, size: %d)", - driverID, channel, ack, len); + gig_dbg(DEBUG_LLDATA, + "Receiving data from LL (id: %d, ch: %d, ack: %d, sz: %d)", + driverID, channel, ack, len); if (!len) { if (ack) - warn("not ACKing empty packet from LL"); + notice("%s: not ACKing empty packet", __func__); return 0; } if (len > MAX_BUF_SIZE) { - err("%s: packet too large (%d bytes)", __func__, channel); + err("%s: packet too large (%d bytes)", __func__, len); return -EINVAL; } - if (!atomic_read(&cs->connected)) - return -ENODEV; - skblen = ack ? len : 0; skb->head[0] = skblen & 0xff; skb->head[1] = skblen >> 8; - dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", len, skblen, - (unsigned) skb->head[0], (unsigned) skb->head[1]); + gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", + len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); /* pass to device-specific module */ return cs->ops->send_skb(bcs, skb); @@ -89,14 +84,14 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) ++bcs->trans_up; if (skb->len) - warn("%s: skb->len==%d", __func__, skb->len); + dev_warn(bcs->cs->dev, "%s: skb->len==%d\n", + __func__, skb->len); len = (unsigned char) skb->head[0] | (unsigned) (unsigned char) skb->head[1] << 8; if (len) { - dbg(DEBUG_MCMD, - "Acknowledge sending to LL (id: %d, channel: %d size: %u)", - bcs->cs->myid, bcs->channel, len); + gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)", + bcs->cs->myid, bcs->channel, len); response.driver = bcs->cs->myid; response.command = ISDN_STAT_BSENT; @@ -119,15 +114,12 @@ static int command_from_LL(isdn_ctrl *cntrl) struct bc_state *bcs; int retval = 0; struct setup_parm *sp; + unsigned param; + unsigned long flags; - //dbg(DEBUG_ANY, "Gigaset_HW: Receiving command"); gigaset_debugdrivers(); - /* Terminate this call if no device is present. Bt if the command is "ISDN_CMD_LOCK" or - * "ISDN_CMD_UNLOCK" then execute it due to the fact that they are device independent ! - */ - //FIXME "remove test for &connected" - if ((!cs || !atomic_read(&cs->connected))) { + if (!cs) { warn("LL tried to access unknown device with nr. %d", cntrl->driver); return -ENODEV; @@ -135,29 +127,30 @@ static int command_from_LL(isdn_ctrl *cntrl) switch (cntrl->command) { case ISDN_CMD_IOCTL: - - dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver:%d,arg: %ld)", - cntrl->driver, cntrl->arg); + gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)", + cntrl->driver, cntrl->arg); warn("ISDN_CMD_IOCTL is not supported."); return -EINVAL; case ISDN_CMD_DIAL: - dbg(DEBUG_ANY, "ISDN_CMD_DIAL (driver: %d, channel: %ld, " - "phone: %s,ownmsn: %s, si1: %d, si2: %d)", - cntrl->driver, cntrl->arg, - cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, - cntrl->parm.setup.si1, cntrl->parm.setup.si2); + gig_dbg(DEBUG_ANY, + "ISDN_CMD_DIAL (driver: %d, ch: %ld, " + "phone: %s, ownmsn: %s, si1: %d, si2: %d)", + cntrl->driver, cntrl->arg, + cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, + cntrl->parm.setup.si1, cntrl->parm.setup.si2); if (cntrl->arg >= cs->channels) { - err("invalid channel (%d)", (int) cntrl->arg); + err("ISDN_CMD_DIAL: invalid channel (%d)", + (int) cntrl->arg); return -EINVAL; } bcs = cs->bcs + cntrl->arg; if (!gigaset_get_channel(bcs)) { - err("channel not free"); + err("ISDN_CMD_DIAL: channel not free"); return -EBUSY; } @@ -169,42 +162,46 @@ static int command_from_LL(isdn_ctrl *cntrl) } *sp = cntrl->parm.setup; - if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, - atomic_read(&bcs->at_state.seq_index), - NULL)) { + spin_lock_irqsave(&cs->lock, flags); + param = bcs->at_state.seq_index; + spin_unlock_irqrestore(&cs->lock, flags); + + if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, param, + NULL)) { //FIXME what should we do? kfree(sp); gigaset_free_channel(bcs); return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling DIAL"); + gig_dbg(DEBUG_CMD, "scheduling DIAL"); gigaset_schedule_event(cs); break; case ISDN_CMD_ACCEPTD: //FIXME - dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); if (cntrl->arg >= cs->channels) { - err("invalid channel (%d)", (int) cntrl->arg); + err("ISDN_CMD_ACCEPTD: invalid channel (%d)", + (int) cntrl->arg); return -EINVAL; } if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, - EV_ACCEPT, NULL, 0, NULL)) { + EV_ACCEPT, NULL, 0, NULL)) { //FIXME what should we do? return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling ACCEPT"); + gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); gigaset_schedule_event(cs); break; case ISDN_CMD_ACCEPTB: - dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB"); break; case ISDN_CMD_HANGUP: - dbg(DEBUG_ANY, - "ISDN_CMD_HANGUP (channel: %d)", (int) cntrl->arg); + gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)", + (int) cntrl->arg); if (cntrl->arg >= cs->channels) { err("ISDN_CMD_HANGUP: invalid channel (%u)", @@ -213,66 +210,68 @@ static int command_from_LL(isdn_ctrl *cntrl) } if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, - EV_HUP, NULL, 0, NULL)) { + EV_HUP, NULL, 0, NULL)) { //FIXME what should we do? return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling HUP"); + gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); break; - case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME - dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); + case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); break; - case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME - dbg(DEBUG_ANY, - "ISDN_CMD_SETEAZ (id:%d, channel: %ld, number: %s)", - cntrl->driver, cntrl->arg, cntrl->parm.num); + case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME + gig_dbg(DEBUG_ANY, + "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)", + cntrl->driver, cntrl->arg, cntrl->parm.num); break; - case ISDN_CMD_SETL2: /* Set L2 to given protocol */ - dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (Channel: %ld, Proto: %lx)", - cntrl->arg & 0xff, (cntrl->arg >> 8)); + case ISDN_CMD_SETL2: /* Set L2 to given protocol */ + gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)", + cntrl->arg & 0xff, (cntrl->arg >> 8)); if ((cntrl->arg & 0xff) >= cs->channels) { - err("invalid channel (%u)", + err("ISDN_CMD_SETL2: invalid channel (%u)", (unsigned) cntrl->arg & 0xff); return -EINVAL; } if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state, - EV_PROTO_L2, NULL, cntrl->arg >> 8, - NULL)) { + EV_PROTO_L2, NULL, cntrl->arg >> 8, + NULL)) { //FIXME what should we do? return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling PROTO_L2"); + gig_dbg(DEBUG_CMD, "scheduling PROTO_L2"); gigaset_schedule_event(cs); break; - case ISDN_CMD_SETL3: /* Set L3 to given protocol */ - dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (Channel: %ld, Proto: %lx)", - cntrl->arg & 0xff, (cntrl->arg >> 8)); + case ISDN_CMD_SETL3: /* Set L3 to given protocol */ + gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)", + cntrl->arg & 0xff, (cntrl->arg >> 8)); if ((cntrl->arg & 0xff) >= cs->channels) { - err("invalid channel (%u)", + err("ISDN_CMD_SETL3: invalid channel (%u)", (unsigned) cntrl->arg & 0xff); return -EINVAL; } if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { - err("invalid protocol %lu", cntrl->arg >> 8); + err("ISDN_CMD_SETL3: invalid protocol %lu", + cntrl->arg >> 8); return -EINVAL; } break; case ISDN_CMD_PROCEED: - dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME break; case ISDN_CMD_ALERT: - dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME if (cntrl->arg >= cs->channels) { - err("invalid channel (%d)", (int) cntrl->arg); + err("ISDN_CMD_ALERT: invalid channel (%d)", + (int) cntrl->arg); return -EINVAL; } //bcs = cs->bcs + cntrl->arg; @@ -280,32 +279,31 @@ static int command_from_LL(isdn_ctrl *cntrl) // FIXME break; case ISDN_CMD_REDIR: - dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME break; case ISDN_CMD_PROT_IO: - dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); break; case ISDN_CMD_FAXCMD: - dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD"); break; case ISDN_CMD_GETL2: - dbg(DEBUG_ANY, "ISDN_CMD_GETL2"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2"); break; case ISDN_CMD_GETL3: - dbg(DEBUG_ANY, "ISDN_CMD_GETL3"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3"); break; case ISDN_CMD_GETEAZ: - dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ"); break; case ISDN_CMD_SETSIL: - dbg(DEBUG_ANY, "ISDN_CMD_SETSIL"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL"); break; case ISDN_CMD_GETSIL: - dbg(DEBUG_ANY, "ISDN_CMD_GETSIL"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL"); break; default: - err("unknown command %d from LL", - cntrl->command); + err("unknown command %d from LL", cntrl->command); return -EINVAL; } @@ -350,7 +348,8 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ break; default: - err("invalid protocol: %u", bcs->proto2); + dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n", + __func__, bcs->proto2); return -EINVAL; } @@ -378,7 +377,7 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) bcs->commands[i] = NULL; if (length[i] && !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { - err("out of memory"); + dev_err(bcs->cs->dev, "out of memory\n"); return -ENOMEM; } } @@ -396,10 +395,14 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) } if (bcs->commands[AT_MSN]) - snprintf(bcs->commands[AT_MSN], length[AT_MSN], "^SMSN=%s\r", sp->eazmsn); - snprintf(bcs->commands[AT_BC ], length[AT_BC ], "^SBC=%s\r", bc); - snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto); - snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned)bcs->channel + 1); + snprintf(bcs->commands[AT_MSN], length[AT_MSN], + "^SMSN=%s\r", sp->eazmsn); + snprintf(bcs->commands[AT_BC ], length[AT_BC ], + "^SBC=%s\r", bc); + snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], + "^SBPR=%u\r", proto); + snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], + "^SISO=%u\r", (unsigned)bcs->channel + 1); return 0; } @@ -419,7 +422,8 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state) proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ break; default: - err("invalid protocol: %u", bcs->proto2); + dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n", + __func__, bcs->proto2); return -EINVAL; } @@ -436,13 +440,15 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state) bcs->commands[i] = NULL; if (length[i] && !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { - err("out of memory"); + dev_err(at_state->cs->dev, "out of memory\n"); return -ENOMEM; } } - snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto); - snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned) bcs->channel + 1); + snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], + "^SBPR=%u\r", proto); + snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], + "^SISO=%u\r", (unsigned) bcs->channel + 1); return 0; } @@ -473,7 +479,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) response.parm.setup.si1 = 1; response.parm.setup.si2 = 2; } else { - warn("RING ignored - unsupported BC %s", + dev_warn(cs->dev, "RING ignored - unsupported BC %s\n", at_state->str_var[STR_ZBC]); return ICALL_IGNORE; } @@ -491,18 +497,17 @@ int gigaset_isdn_icall(struct at_state_t *at_state) response.parm.setup.eazmsn[0] = 0; if (!bcs) { - notice("no channel for incoming call"); - dbg(DEBUG_CMD, "Sending ICALLW"); + dev_notice(cs->dev, "no channel for incoming call\n"); response.command = ISDN_STAT_ICALLW; response.arg = 0; //FIXME } else { - dbg(DEBUG_CMD, "Sending ICALL"); + gig_dbg(DEBUG_CMD, "Sending ICALL"); response.command = ISDN_STAT_ICALL; response.arg = bcs->channel; //FIXME } response.driver = cs->myid; retval = cs->iif.statcallb(&response); - dbg(DEBUG_CMD, "Response: %d", retval); + gig_dbg(DEBUG_CMD, "Response: %d", retval); switch (retval) { case 0: /* no takers */ return ICALL_IGNORE; @@ -512,7 +517,8 @@ int gigaset_isdn_icall(struct at_state_t *at_state) case 2: /* reject */ return ICALL_REJECT; case 3: /* incomplete */ - warn("LL requested unsupported feature: Incomplete Number"); + dev_warn(cs->dev, + "LL requested unsupported feature: Incomplete Number\n"); return ICALL_IGNORE; case 4: /* proceeding */ /* Gigaset will send ALERTING anyway. @@ -520,10 +526,11 @@ int gigaset_isdn_icall(struct at_state_t *at_state) */ return ICALL_ACCEPT; case 5: /* deflect */ - warn("LL requested unsupported feature: Call Deflection"); + dev_warn(cs->dev, + "LL requested unsupported feature: Call Deflection\n"); return ICALL_IGNORE; default: - err("LL error %d on ICALL", retval); + dev_err(cs->dev, "LL error %d on ICALL\n", retval); return ICALL_IGNORE; } } @@ -533,7 +540,7 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) { isdn_if *iif = &cs->iif; - dbg(DEBUG_ANY, "Register driver capabilities to LL"); + gig_dbg(DEBUG_ANY, "Register driver capabilities to LL"); //iif->id[sizeof(iif->id) - 1]=0; //strncpy(iif->id, isdnid, sizeof(iif->id) - 1); @@ -542,26 +549,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) return -ENOMEM; //FIXME EINVAL/...?? iif->owner = THIS_MODULE; - iif->channels = cs->channels; /* I am supporting just one channel *//* I was supporting...*/ + iif->channels = cs->channels; iif->maxbufsize = MAX_BUF_SIZE; - iif->features = ISDN_FEATURE_L2_TRANS | /* Our device is very advanced, therefore */ + iif->features = ISDN_FEATURE_L2_TRANS | ISDN_FEATURE_L2_HDLC | #ifdef GIG_X75 ISDN_FEATURE_L2_X75I | #endif ISDN_FEATURE_L3_TRANS | ISDN_FEATURE_P_EURO; - iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */ + iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */ iif->command = command_from_LL; iif->writebuf_skb = writebuf_from_LL; - iif->writecmd = NULL; /* Don't support isdnctrl */ - iif->readstat = NULL; /* Don't support isdnctrl */ - iif->rcvcallb_skb = NULL; /* Will be set by LL */ - iif->statcallb = NULL; /* Will be set by LL */ + iif->writecmd = NULL; /* Don't support isdnctrl */ + iif->readstat = NULL; /* Don't support isdnctrl */ + iif->rcvcallb_skb = NULL; /* Will be set by LL */ + iif->statcallb = NULL; /* Will be set by LL */ if (!register_isdn(iif)) return 0; - cs->myid = iif->channels; /* Set my device id */ + cs->myid = iif->channels; /* Set my device id */ return 1; } diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 3a81d9c..08e4c4e 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -9,8 +9,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * Version: $Id: interface.c,v 1.14.4.15 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -24,7 +22,7 @@ static int if_lock(struct cardstate *cs, int *arg) { int cmd = *arg; - dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd); + gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd); if (cmd > 1) return -EINVAL; @@ -35,7 +33,7 @@ static int if_lock(struct cardstate *cs, int *arg) } if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED - && atomic_read(&cs->connected)) { + && 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); @@ -44,12 +42,12 @@ static int if_lock(struct cardstate *cs, int *arg) cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK, - NULL, cmd, NULL)) { + NULL, cmd, NULL)) { cs->waiting = 0; return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling IF_LOCK"); + gig_dbg(DEBUG_CMD, "scheduling IF_LOCK"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -68,7 +66,7 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) static const unsigned compat[4] = GIG_COMPAT; unsigned cmd = arg[0]; - dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd); + gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd); switch (cmd) { case GIGVER_DRIVER: @@ -80,12 +78,12 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) case GIGVER_FWBASE: cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER, - NULL, 0, arg)) { + NULL, 0, arg)) { cs->waiting = 0; return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling IF_VER"); + gig_dbg(DEBUG_CMD, "scheduling IF_VER"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -101,7 +99,7 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) static int if_config(struct cardstate *cs, int *arg) { - dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg); + gig_dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg); if (*arg != 1) return -EINVAL; @@ -109,6 +107,11 @@ static int if_config(struct cardstate *cs, int *arg) if (atomic_read(&cs->mstate) != MS_LOCKED) return -EBUSY; + if (!cs->connected) { + err("not connected!"); + return -ENODEV; + } + *arg = 0; return gigaset_enterconfigmode(cs); } @@ -119,7 +122,7 @@ static int if_config(struct cardstate *cs, int *arg) static int if_open(struct tty_struct *tty, struct file *filp); static void if_close(struct tty_struct *tty, struct file *filp); static int if_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg); + unsigned int cmd, unsigned long arg); static int if_write_room(struct tty_struct *tty); static int if_chars_in_buffer(struct tty_struct *tty); static void if_throttle(struct tty_struct *tty); @@ -127,9 +130,9 @@ static void if_unthrottle(struct tty_struct *tty); static void if_set_termios(struct tty_struct *tty, struct termios *old); static int if_tiocmget(struct tty_struct *tty, struct file *file); static int if_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear); + unsigned int set, unsigned int clear); static int if_write(struct tty_struct *tty, - const unsigned char *buf, int count); + const unsigned char *buf, int count); static struct tty_operations if_ops = { .open = if_open, @@ -153,8 +156,8 @@ static int if_open(struct tty_struct *tty, struct file *filp) struct cardstate *cs; unsigned long flags; - dbg(DEBUG_IF, "%d+%d: %s()", tty->driver->minor_start, tty->index, - __FUNCTION__); + gig_dbg(DEBUG_IF, "%d+%d: %s()", + tty->driver->minor_start, tty->index, __func__); tty->driver_data = NULL; @@ -162,7 +165,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) if (!cs) return -ENODEV; - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? tty->driver_data = cs; @@ -173,10 +176,9 @@ static int if_open(struct tty_struct *tty, struct file *filp) cs->tty = tty; spin_unlock_irqrestore(&cs->lock, flags); tty->low_latency = 1; //FIXME test - //FIXME } - up(&cs->sem); + mutex_unlock(&cs->mutex); return 0; } @@ -187,30 +189,29 @@ static void if_close(struct tty_struct *tty, struct file *filp) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else { if (!--cs->open_count) { spin_lock_irqsave(&cs->lock, flags); cs->tty = NULL; spin_unlock_irqrestore(&cs->lock, flags); - //FIXME } } - up(&cs->sem); + mutex_unlock(&cs->mutex); } static int if_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { struct cardstate *cs; int retval = -ENODEV; @@ -220,17 +221,17 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __FUNCTION__, cmd); + gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else { retval = 0; switch (cmd) { @@ -250,37 +251,40 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, break; case GIGASET_BRKCHARS: //FIXME test if MS_LOCKED - gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS", - 6, (const unsigned char *) arg, 1); - if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't communicate with unplugged device"); + if (!cs->connected) { + gig_dbg(DEBUG_ANY, + "can't communicate with unplugged device"); retval = -ENODEV; break; } retval = copy_from_user(&buf, - (const unsigned char __user *) arg, 6) - ? -EFAULT : 0; - if (retval >= 0) + (const unsigned char __user *) arg, 6) + ? -EFAULT : 0; + if (retval >= 0) { + gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS", + 6, (const unsigned char *) arg); retval = cs->ops->brkchars(cs, buf); + } break; case GIGASET_VERSION: - retval = copy_from_user(version, (unsigned __user *) arg, - sizeof version) ? -EFAULT : 0; + retval = copy_from_user(version, + (unsigned __user *) arg, sizeof version) + ? -EFAULT : 0; if (retval >= 0) retval = if_version(cs, version); if (retval >= 0) - retval = copy_to_user((unsigned __user *) arg, version, - sizeof version) - ? -EFAULT : 0; + retval = copy_to_user((unsigned __user *) arg, + version, sizeof version) + ? -EFAULT : 0; break; - default: - dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x", - __FUNCTION__, cmd); + default: + gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x", + __func__, cmd); retval = -ENOIOCTLCMD; } } - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -292,25 +296,25 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? // FIXME read from device? retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } static int if_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) + unsigned int set, unsigned int clear) { struct cardstate *cs; int retval; @@ -318,18 +322,18 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file, cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, - "%u: %s(0x%x, 0x%x)", cs->minor_index, __FUNCTION__, set, clear); + gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)", + cs->minor_index, __func__, set, clear); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? - if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't communicate with unplugged device"); + if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't communicate with unplugged device"); retval = -ENODEV; } else { mc = (cs->control_state | set) & ~clear & (TIOCM_RTS|TIOCM_DTR); @@ -337,7 +341,7 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file, cs->control_state = mc; } - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -349,29 +353,29 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else if (atomic_read(&cs->mstate) != MS_LOCKED) { warn("can't write to unlocked device"); retval = -EBUSY; - } else if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't write to unplugged device"); + } else if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't write to unplugged device"); retval = -EBUSY; //FIXME } else { retval = cs->ops->write_cmd(cs, buf, count, - &cs->if_wake_tasklet); + &cs->if_wake_tasklet); } - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -383,27 +387,27 @@ static int if_write_room(struct tty_struct *tty) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else if (atomic_read(&cs->mstate) != MS_LOCKED) { warn("can't write to unlocked device"); retval = -EBUSY; //FIXME - } else if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't write to unplugged device"); + } else if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't write to unplugged device"); retval = -EBUSY; //FIXME } else retval = cs->ops->write_room(cs); - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -415,27 +419,27 @@ static int if_chars_in_buffer(struct tty_struct *tty) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else if (atomic_read(&cs->mstate) != MS_LOCKED) { warn("can't write to unlocked device"); retval = -EBUSY; - } else if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't write to unplugged device"); + } else if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't write to unplugged device"); retval = -EBUSY; //FIXME } else retval = cs->ops->chars_in_buffer(cs); - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -446,21 +450,21 @@ static void if_throttle(struct tty_struct *tty) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else { //FIXME } - up(&cs->sem); + mutex_unlock(&cs->mutex); } static void if_unthrottle(struct tty_struct *tty) @@ -469,21 +473,21 @@ static void if_unthrottle(struct tty_struct *tty) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else { //FIXME } - up(&cs->sem); + mutex_unlock(&cs->mutex); } static void if_set_termios(struct tty_struct *tty, struct termios *old) @@ -496,21 +500,21 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->open_count) { - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); goto out; } - if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't communicate with unplugged device"); + if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't communicate with unplugged device"); goto out; } @@ -518,8 +522,8 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) iflag = tty->termios->c_iflag; cflag = tty->termios->c_cflag; old_cflag = old ? old->c_cflag : cflag; //FIXME? - dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index, - iflag, cflag, old_cflag); + gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", + cs->minor_index, iflag, cflag, old_cflag); /* get a local copy of the current port settings */ control_state = cs->control_state; @@ -531,14 +535,15 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) * Premature optimization is the root of all evil. */ - /* reassert DTR and (maybe) RTS on transition from B0 */ + /* reassert DTR and (maybe) RTS on transition from B0 */ if ((old_cflag & CBAUD) == B0) { new_state = control_state | TIOCM_DTR; /* don't set RTS if using hardware flow control */ if (!(old_cflag & CRTSCTS)) new_state |= TIOCM_RTS; - dbg(DEBUG_IF, "%u: from B0 - set DTR%s", cs->minor_index, - (new_state & TIOCM_RTS) ? " only" : "/RTS"); + gig_dbg(DEBUG_IF, "%u: from B0 - set DTR%s", + cs->minor_index, + (new_state & TIOCM_RTS) ? " only" : "/RTS"); cs->ops->set_modem_ctrl(cs, control_state, new_state); control_state = new_state; } @@ -547,7 +552,7 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) if ((cflag & CBAUD) == B0) { /* Drop RTS and DTR */ - dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index); + gig_dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index); new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS); cs->ops->set_modem_ctrl(cs, control_state, new_state); control_state = new_state; @@ -567,15 +572,17 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) * Just do what we have seen with SniffUSB on Win98. */ /* Drop DTR/RTS if no flow control otherwise assert */ - dbg(DEBUG_IF, "%u: control_state %x", cs->minor_index, control_state); + gig_dbg(DEBUG_IF, "%u: control_state %x", + cs->minor_index, control_state); new_state = control_state; if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) new_state |= TIOCM_DTR | TIOCM_RTS; else new_state &= ~(TIOCM_DTR | TIOCM_RTS); if (new_state != control_state) { - dbg(DEBUG_IF, "%u: new_state %x", cs->minor_index, new_state); - gigaset_set_modem_ctrl(cs, control_state, new_state); // FIXME: mct_u232.c sets the old state here. is this a bug? + gig_dbg(DEBUG_IF, "%u: new_state %x", + cs->minor_index, new_state); + gigaset_set_modem_ctrl(cs, control_state, new_state); control_state = new_state; } #endif @@ -584,7 +591,7 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) cs->control_state = control_state; out: - up(&cs->sem); + mutex_unlock(&cs->mutex); } @@ -600,7 +607,7 @@ static void if_wake(unsigned long data) if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { - dbg(DEBUG_IF, "write wakeup call"); + gig_dbg(DEBUG_IF, "write wakeup call"); tty->ldisc.write_wakeup(tty); } @@ -635,14 +642,14 @@ void gigaset_if_free(struct cardstate *cs) } void gigaset_if_receive(struct cardstate *cs, - unsigned char *buffer, size_t len) + unsigned char *buffer, size_t len) { unsigned long flags; struct tty_struct *tty; spin_lock_irqsave(&cs->lock, flags); if ((tty = cs->tty) == NULL) - dbg(DEBUG_ANY, "receive on closed device"); + gig_dbg(DEBUG_ANY, "receive on closed device"); else { tty_buffer_request_room(tty, len); tty_insert_flip_string(tty, buffer, len); @@ -655,13 +662,13 @@ EXPORT_SYMBOL_GPL(gigaset_if_receive); /* gigaset_if_initdriver * Initialize tty interface. * parameters: - * drv Driver - * procname Name of the driver (e.g. for /proc/tty/drivers) - * devname Name of the device files (prefix without minor number) - * devfsname Devfs name of the device files without %d + * drv Driver + * procname Name of the driver (e.g. for /proc/tty/drivers) + * devname Name of the device files (prefix without minor number) + * devfsname Devfs name of the device files without %d */ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, - const char *devname, const char *devfsname) + const char *devname, const char *devfsname) { unsigned minors = drv->minors; int ret; @@ -696,7 +703,7 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, warn("failed to register tty driver (error %d)", ret); goto error; } - dbg(DEBUG_IF, "tty driver initialized"); + gig_dbg(DEBUG_IF, "tty driver initialized"); drv->have_tty = 1; return; diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 5744eb9..8667daa 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -10,10 +10,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: isocdata.c,v 1.2.2.5 2005/11/13 23:05:19 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -87,14 +83,14 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb) { if (!atomic_dec_and_test(&iwb->writesem)) { atomic_inc(&iwb->writesem); - dbg(DEBUG_ISO, - "%s: couldn't acquire iso write semaphore", __func__); + gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore", + __func__); return 0; } #ifdef CONFIG_GIGASET_DEBUG - dbg(DEBUG_ISO, - "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", - __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits); + gig_dbg(DEBUG_ISO, + "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", + __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits); #endif return 1; } @@ -147,7 +143,7 @@ static inline void isowbuf_putflag(struct isowbuf_t *iwb) /* recover the idle flag byte */ write = atomic_read(&iwb->write); iwb->idle = iwb->data[write]; - dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); + gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); /* mask extraneous bits in buffer */ iwb->data[write] &= (1 << iwb->wbits) - 1; } @@ -166,15 +162,14 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) read = atomic_read(&iwb->nextread); write = atomic_read(&iwb->write); if (likely(read == write)) { - //dbg(DEBUG_STREAM, "%s: send buffer empty", __func__); /* return idle frame */ return read < BAS_OUTBUFPAD ? - BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD; + BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD; } limit = read + size; - dbg(DEBUG_STREAM, - "%s: read=%d write=%d limit=%d", __func__, read, write, limit); + gig_dbg(DEBUG_STREAM, "%s: read=%d write=%d limit=%d", + __func__, read, write, limit); #ifdef CONFIG_GIGASET_DEBUG if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) { err("invalid size %d", size); @@ -196,11 +191,12 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) return -EBUSY; /* write position could have changed */ if (limit >= (write = atomic_read(&iwb->write))) { - pbyte = iwb->data[write]; /* save partial byte */ + pbyte = iwb->data[write]; /* save + partial byte */ limit = write + BAS_OUTBUFPAD; - dbg(DEBUG_STREAM, - "%s: filling %d->%d with %02x", - __func__, write, limit, iwb->idle); + gig_dbg(DEBUG_STREAM, + "%s: filling %d->%d with %02x", + __func__, write, limit, iwb->idle); if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE) memset(iwb->data + write, iwb->idle, BAS_OUTBUFPAD); @@ -211,9 +207,11 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) - write); limit = 0; } - dbg(DEBUG_STREAM, "%s: restoring %02x at %d", - __func__, pbyte, limit); - iwb->data[limit] = pbyte; /* restore partial byte */ + gig_dbg(DEBUG_STREAM, + "%s: restoring %02x at %d", + __func__, pbyte, limit); + iwb->data[limit] = pbyte; /* restore + partial byte */ atomic_set(&iwb->write, limit); } isowbuf_donewrite(iwb); @@ -242,19 +240,17 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) * write hex bytes to syslog for debugging */ static inline void dump_bytes(enum debuglevel level, const char *tag, - unsigned char *bytes, int count) + unsigned char *bytes, int count) { #ifdef CONFIG_GIGASET_DEBUG unsigned char c; static char dbgline[3 * 32 + 1]; static const char hexdigit[] = "0123456789abcdef"; int i = 0; - IFNULLRET(tag); - IFNULLRET(bytes); while (count-- > 0) { if (i > sizeof(dbgline) - 4) { dbgline[i] = '\0'; - dbg(level, "%s:%s", tag, dbgline); + gig_dbg(level, "%s:%s", tag, dbgline); i = 0; } c = *bytes++; @@ -264,7 +260,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag, dbgline[i++] = hexdigit[c & 0x0f]; } dbgline[i] = '\0'; - dbg(level, "%s:%s", tag, dbgline); + gig_dbg(level, "%s:%s", tag, dbgline); #endif } @@ -380,7 +376,7 @@ static u16 stufftab[5 * 256] = { */ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, - int ones) + int ones) { u16 stuff; int shiftinc, newones; @@ -422,7 +418,7 @@ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, */ static inline int hdlc_buildframe(struct isowbuf_t *iwb, - unsigned char *in, int count) + unsigned char *in, int count) { int ones; u16 fcs; @@ -431,8 +427,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, if (isowbuf_freebytes(iwb) < count + count / 5 + 6 || !isowbuf_startwrite(iwb)) { - dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN", - __func__, isowbuf_freebytes(iwb)); + gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN", + __func__, isowbuf_freebytes(iwb)); return -EAGAIN; } @@ -484,11 +480,11 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, if (isowbuf_freebytes(iwb) < count || !isowbuf_startwrite(iwb)) { - dbg(DEBUG_ISO, "can't put %d bytes", count); + gig_dbg(DEBUG_ISO, "can't put %d bytes", count); return -EAGAIN; } - dbg(DEBUG_STREAM, "put %d bytes", count); + gig_dbg(DEBUG_STREAM, "put %d bytes", count); write = atomic_read(&iwb->write); do { c = gigaset_invtab[*in++]; @@ -508,11 +504,13 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) switch (bcs->proto2) { case ISDN_PROTO_L2_HDLC: result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); - dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", __func__, len, result); + gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", + __func__, len, result); break; default: /* assume transparent */ result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len); - dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", __func__, len, result); + gig_dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", + __func__, len, result); } return result; } @@ -528,13 +526,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) return; } if (unlikely(bcs->skb->len == SBUFSIZE)) { - warn("received oversized packet discarded"); + dev_warn(bcs->cs->dev, "received oversized packet discarded\n"); bcs->hw.bas->giants++; dev_kfree_skb_any(bcs->skb); bcs->skb = NULL; return; } - *gigaset_skb_put_quick(bcs->skb, 1) = c; + *__skb_put(bcs->skb, 1) = c; } /* hdlc_flush @@ -549,7 +547,7 @@ static inline void hdlc_flush(struct bc_state *bcs) if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else - err("could not allocate skb"); + dev_err(bcs->cs->dev, "could not allocate skb\n"); } /* reset packet state */ @@ -571,23 +569,25 @@ static inline void hdlc_done(struct bc_state *bcs) if ((procskb = bcs->skb) == NULL) { /* previous error */ - dbg(DEBUG_ISO, "%s: skb=NULL", __func__); + gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); gigaset_rcv_error(NULL, bcs->cs, bcs); } else if (procskb->len < 2) { - notice("received short frame (%d octets)", procskb->len); + dev_notice(bcs->cs->dev, "received short frame (%d octets)\n", + procskb->len); bcs->hw.bas->runts++; gigaset_rcv_error(procskb, bcs->cs, bcs); } else if (bcs->fcs != PPP_GOODFCS) { - notice("frame check error (0x%04x)", bcs->fcs); + dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n", + bcs->fcs); bcs->hw.bas->fcserrs++; gigaset_rcv_error(procskb, bcs->cs, bcs); } else { procskb->len -= 2; /* subtract FCS */ procskb->tail -= 2; - dbg(DEBUG_ISO, - "%s: good frame (%d octets)", __func__, procskb->len); + gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", + __func__, procskb->len); dump_bytes(DEBUG_STREAM, - "rcv data", procskb->data, procskb->len); + "rcv data", procskb->data, procskb->len); bcs->hw.bas->goodbytes += procskb->len; gigaset_rcv_skb(procskb, bcs->cs, bcs); } @@ -595,7 +595,7 @@ static inline void hdlc_done(struct bc_state *bcs) if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else - err("could not allocate skb"); + dev_err(bcs->cs->dev, "could not allocate skb\n"); bcs->fcs = PPP_INITFCS; } @@ -610,14 +610,14 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) return; } - notice("received partial byte (%d bits)", inbits); + dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); bcs->hw.bas->alignerrs++; gigaset_rcv_error(bcs->skb, bcs->cs, bcs); if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else - err("could not allocate skb"); + dev_err(bcs->cs->dev, "could not allocate skb\n"); bcs->fcs = PPP_INITFCS; } @@ -659,16 +659,12 @@ static unsigned char bitcounts[256] = { * bcs receiving B channel structure */ static inline void hdlc_unpack(unsigned char *src, unsigned count, - struct bc_state *bcs) + struct bc_state *bcs) { - struct bas_bc_state *ubc; + struct bas_bc_state *ubc = bcs->hw.bas; int inputstate; unsigned seqlen, inbyte, inbits; - IFNULLRET(bcs); - ubc = bcs->hw.bas; - IFNULLRET(ubc); - /* load previous state: * inputstate = set of flag bits: * - INS_flag_hunt: no complete opening flag received since connection setup or last abort @@ -856,7 +852,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, * bcs receiving B channel structure */ static inline void trans_receive(unsigned char *src, unsigned count, - struct bc_state *bcs) + struct bc_state *bcs) { struct sk_buff *skb; int dobytes; @@ -870,7 +866,7 @@ static inline void trans_receive(unsigned char *src, unsigned count, if (unlikely((skb = bcs->skb) == NULL)) { bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); if (!skb) { - err("could not allocate skb"); + dev_err(bcs->cs->dev, "could not allocate skb\n"); return; } skb_reserve(skb, HW_HDR_LEN); @@ -888,7 +884,8 @@ static inline void trans_receive(unsigned char *src, unsigned count, gigaset_rcv_skb(skb, bcs->cs, bcs); bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); if (!skb) { - err("could not allocate skb"); + dev_err(bcs->cs->dev, + "could not allocate skb\n"); return; } skb_reserve(bcs->skb, HW_HDR_LEN); @@ -921,8 +918,8 @@ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) case '\r': case '\n': /* end of line */ - dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", - __func__, cbytes); + gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", + __func__, cbytes); cs->cbytes = cbytes; gigaset_handle_modem_response(cs); cbytes = 0; @@ -932,7 +929,7 @@ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) if (cbytes < MAX_RESP_SIZE - 1) cbytes++; else - warn("response too large"); + dev_warn(cs->dev, "response too large\n"); } } @@ -951,27 +948,27 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) head = atomic_read(&inbuf->head); while (head != (tail = atomic_read(&inbuf->tail))) { - dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); + gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); if (head > tail) tail = RBUFSIZE; src = inbuf->data + head; numbytes = tail - head; - dbg(DEBUG_INTR, "processing %u bytes", numbytes); + gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); if (atomic_read(&cs->mstate) == MS_LOCKED) { gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", - numbytes, src, 0); + numbytes, src); gigaset_if_receive(inbuf->cs, src, numbytes); } else { gigaset_dbg_buffer(DEBUG_CMD, "received response", - numbytes, src, 0); + numbytes, src); cmd_loop(src, numbytes, inbuf); } head += numbytes; if (head == RBUFSIZE) head = 0; - dbg(DEBUG_INTR, "setting head to %u", head); + gig_dbg(DEBUG_INTR, "setting head to %u", head); atomic_set(&inbuf->head, head); } } @@ -992,18 +989,22 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) */ int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb) { - int len; + int len = skb->len; + unsigned long flags; - IFNULLRETVAL(bcs, -EFAULT); - IFNULLRETVAL(skb, -EFAULT); - len = skb->len; + spin_lock_irqsave(&bcs->cs->lock, flags); + if (!bcs->cs->connected) { + spin_unlock_irqrestore(&bcs->cs->lock, flags); + return -ENODEV; + } skb_queue_tail(&bcs->squeue, skb); - dbg(DEBUG_ISO, - "%s: skb queued, qlen=%d", __func__, skb_queue_len(&bcs->squeue)); + gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d", + __func__, skb_queue_len(&bcs->squeue)); /* tasklet submits URB if necessary */ tasklet_schedule(&bcs->hw.bas->sent_tasklet); + spin_unlock_irqrestore(&bcs->cs->lock, flags); return len; /* ok so far */ } diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index c6915fa..d267a63 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -1,7 +1,7 @@ /* * Stuff used by all variants of the driver * - * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>, + * Copyright (c) 2001 by Stefan Eilers, * Hansjoerg Lipp <hjlipp@web.de>, * Tilman Schmidt <tilman@imap.cc>. * @@ -11,26 +11,29 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: proc.c,v 1.5.2.13 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" #include <linux/ctype.h> -static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, + char *buf) { - struct usb_interface *intf = to_usb_interface(dev); - struct cardstate *cs = usb_get_intfdata(intf); - return sprintf(buf, "%d\n", atomic_read(&cs->cidmode)); // FIXME use scnprintf for 13607 bit architectures (if PAGE_SIZE==4096) + int ret; + unsigned long flags; + struct cardstate *cs = dev_get_drvdata(dev); + + spin_lock_irqsave(&cs->lock, flags); + ret = sprintf(buf, "%u\n", cs->cidmode); + spin_unlock_irqrestore(&cs->lock, flags); + + return ret; } -static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - struct usb_interface *intf = to_usb_interface(dev); - struct cardstate *cs = usb_get_intfdata(intf); + struct cardstate *cs = dev_get_drvdata(dev); long int value; char *end; @@ -41,23 +44,23 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, co if (value < 0 || value > 1) return -EINVAL; - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, - NULL, value, NULL)) { + NULL, value, NULL)) { cs->waiting = 0; - up(&cs->sem); + mutex_unlock(&cs->mutex); return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling PROC_CIDMODE"); + gig_dbg(DEBUG_CMD, "scheduling PROC_CIDMODE"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); - up(&cs->sem); + mutex_unlock(&cs->mutex); return count; } @@ -65,17 +68,15 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, co static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode); /* free sysfs for device */ -void gigaset_free_dev_sysfs(struct usb_interface *interface) +void gigaset_free_dev_sysfs(struct cardstate *cs) { - dbg(DEBUG_INIT, "removing sysfs entries"); - device_remove_file(&interface->dev, &dev_attr_cidmode); + gig_dbg(DEBUG_INIT, "removing sysfs entries"); + device_remove_file(cs->dev, &dev_attr_cidmode); } -EXPORT_SYMBOL_GPL(gigaset_free_dev_sysfs); /* initialize sysfs for device */ -void gigaset_init_dev_sysfs(struct usb_interface *interface) +void gigaset_init_dev_sysfs(struct cardstate *cs) { - dbg(DEBUG_INIT, "setting up sysfs"); - device_create_file(&interface->dev, &dev_attr_cidmode); + gig_dbg(DEBUG_INIT, "setting up sysfs"); + device_create_file(cs->dev, &dev_attr_cidmode); } -EXPORT_SYMBOL_GPL(gigaset_init_dev_sysfs); diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 323fc73..bfb73fd 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -1,7 +1,7 @@ /* * USB driver for Gigaset 307x directly or using M105 Data. * - * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de> + * Copyright (c) 2001 by Stefan Eilers * and Hansjoerg Lipp <hjlipp@web.de>. * * This driver was derived from the USB skeleton driver by @@ -13,10 +13,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: usb-gigaset.c,v 1.85.4.18 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -29,7 +25,7 @@ #include <linux/moduleparam.h> /* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>" +#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers" #define DRIVER_DESC "USB Driver for Gigaset 307x using M105" /* Module parameters */ @@ -62,10 +58,6 @@ static struct usb_device_id gigaset_table [] = { MODULE_DEVICE_TABLE(usb, gigaset_table); -/* Get a minor range for your devices from the usb maintainer */ -#define USB_SKEL_MINOR_BASE 200 - - /* * Control requests (empty fields: 00) * @@ -114,7 +106,7 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); */ static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id); + const struct usb_device_id *id); static void gigaset_disconnect(struct usb_interface *interface); static struct gigaset_driver *driver = NULL; @@ -122,29 +114,29 @@ static struct cardstate *cardstate = NULL; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { - .name = GIGASET_MODULENAME, - .probe = gigaset_probe, - .disconnect = gigaset_disconnect, - .id_table = gigaset_table, + .name = GIGASET_MODULENAME, + .probe = gigaset_probe, + .disconnect = gigaset_disconnect, + .id_table = gigaset_table, }; struct usb_cardstate { - struct usb_device *udev; /* save off the usb device pointer */ - struct usb_interface *interface; /* the interface for this device */ - atomic_t busy; /* bulk output in progress */ - - /* Output buffer for commands (M105: and data)*/ - unsigned char *bulk_out_buffer; /* the buffer to send data */ - int bulk_out_size; /* the size of the send buffer */ - __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ - struct urb *bulk_out_urb; /* the urb used to transmit data */ - - /* Input buffer for command responses (M105: and data)*/ - int rcvbuf_size; /* the size of the receive buffer */ - struct urb *read_urb; /* the urb used to receive data */ - __u8 int_in_endpointAddr; /* the address of the bulk in endpoint */ - - char bchars[6]; /* req. 0x19 */ + struct usb_device *udev; /* usb device pointer */ + struct usb_interface *interface; /* interface for this device */ + atomic_t busy; /* bulk output in progress */ + + /* Output buffer */ + unsigned char *bulk_out_buffer; + int bulk_out_size; + __u8 bulk_out_endpointAddr; + struct urb *bulk_out_urb; + + /* Input buffer */ + int rcvbuf_size; + struct urb *read_urb; + __u8 int_in_endpointAddr; + + char bchars[6]; /* for request 0x19 */ }; struct usb_bc_state {}; @@ -157,19 +149,20 @@ static inline unsigned tiocm_to_gigaset(unsigned state) #ifdef CONFIG_GIGASET_UNDOCREQ /* WARNING: EXPERIMENTAL! */ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) + unsigned new_state) { + struct usb_device *udev = cs->hw.usb->udev; unsigned mask, val; int r; mask = tiocm_to_gigaset(old_state ^ new_state); val = tiocm_to_gigaset(new_state); - dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); - r = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 7, 0x41, - (val & 0xff) | ((mask & 0xff) << 8), 0, - NULL, 0, 2000 /*timeout??*/); // don't use this in an interrupt/BH + gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); + // don't use this in an interrupt/BH + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, + (val & 0xff) | ((mask & 0xff) << 8), 0, + NULL, 0, 2000 /* timeout? */); if (r < 0) return r; //.. @@ -178,30 +171,29 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, static int set_value(struct cardstate *cs, u8 req, u16 val) { + struct usb_device *udev = cs->hw.usb->udev; int r, r2; - dbg(DEBUG_USBREQ, "request %02x (%04x)", (unsigned)req, (unsigned)val); - r = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x12, 0x41, - 0xf /*?*/, 0, - NULL, 0, 2000 /*?*/); /* no idea, what this does */ + gig_dbg(DEBUG_USBREQ, "request %02x (%04x)", + (unsigned)req, (unsigned)val); + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41, + 0xf /*?*/, 0, NULL, 0, 2000 /*?*/); + /* no idea what this does */ if (r < 0) { - err("error %d on request 0x12", -r); + dev_err(&udev->dev, "error %d on request 0x12\n", -r); return r; } - r = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), req, 0x41, - val, 0, - NULL, 0, 2000 /*?*/); + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, 0x41, + val, 0, NULL, 0, 2000 /*?*/); if (r < 0) - err("error %d on request 0x%02x", -r, (unsigned)req); + dev_err(&udev->dev, "error %d on request 0x%02x\n", + -r, (unsigned)req); - r2 = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41, - 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/); + r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, + 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/); if (r2 < 0) - err("error %d on request 0x19", -r2); + dev_err(&udev->dev, "error %d on request 0x19\n", -r2); return r < 0 ? r : (r2 < 0 ? r2 : 0); } @@ -229,8 +221,8 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) case B115200: rate = 115200; break; default: rate = 9600; - err("unsupported baudrate request 0x%x," - " using default of B9600", cflag); + dev_err(cs->dev, "unsupported baudrate request 0x%x," + " using default of B9600\n", cflag); } val = 0x383fff / rate + 1; @@ -259,7 +251,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) case CS8: val |= 8 << 8; break; default: - err("CSIZE was not CS5-CS8, using default of 8"); + dev_err(cs->dev, "CSIZE was not CS5-CS8, using default of 8\n"); val |= 8 << 8; break; } @@ -277,7 +269,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) #else static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) + unsigned new_state) { return -EINVAL; } @@ -309,15 +301,12 @@ static int gigaset_close_bchannel(struct bc_state *bcs) return 0; } -//void send_ack_to_LL(void *data); static int write_modem(struct cardstate *cs); static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb); -/* Handling of send queue. If there is already a skb opened, put data to - * the transfer buffer by calling "write_modem". Otherwise take a new skb out of the queue. - * This function will be called by the ISR via "transmit_chars" (USB: B-Channel Bulk callback handler - * via immediate task queue) or by writebuf_from_LL if the LL wants to transmit data. +/* Write tasklet handler: Continue sending current skb, or send command, or + * start sending an skb from the send queue. */ static void gigaset_modem_fill(unsigned long data) { @@ -327,10 +316,10 @@ static void gigaset_modem_fill(unsigned long data) unsigned long flags; int again; - dbg(DEBUG_OUTPUT, "modem_fill"); + gig_dbg(DEBUG_OUTPUT, "modem_fill"); if (atomic_read(&cs->hw.usb->busy)) { - dbg(DEBUG_OUTPUT, "modem_fill: busy"); + gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); return; } @@ -341,26 +330,27 @@ static void gigaset_modem_fill(unsigned long data) cb = cs->cmdbuf; spin_unlock_irqrestore(&cs->cmdlock, flags); if (cb) { /* commands to send? */ - dbg(DEBUG_OUTPUT, "modem_fill: cb"); + gig_dbg(DEBUG_OUTPUT, "modem_fill: cb"); if (send_cb(cs, cb) < 0) { - dbg(DEBUG_OUTPUT, - "modem_fill: send_cb failed"); - again = 1; /* no callback will be called! */ + gig_dbg(DEBUG_OUTPUT, + "modem_fill: send_cb failed"); + again = 1; /* no callback will be + called! */ } } else { /* skbs to send? */ bcs->tx_skb = skb_dequeue(&bcs->squeue); if (bcs->tx_skb) - dbg(DEBUG_INTR, - "Dequeued skb (Adr: %lx)!", - (unsigned long) bcs->tx_skb); + gig_dbg(DEBUG_INTR, + "Dequeued skb (Adr: %lx)!", + (unsigned long) bcs->tx_skb); } } if (bcs->tx_skb) { - dbg(DEBUG_OUTPUT, "modem_fill: tx_skb"); + gig_dbg(DEBUG_OUTPUT, "modem_fill: tx_skb"); if (write_modem(cs) < 0) { - dbg(DEBUG_OUTPUT, - "modem_fill: write_modem failed"); + gig_dbg(DEBUG_OUTPUT, + "modem_fill: write_modem failed"); // FIXME should we tell the LL? again = 1; /* no callback will be called! */ } @@ -371,88 +361,85 @@ static void gigaset_modem_fill(unsigned long data) /** * gigaset_read_int_callback * - * It is called if the data was received from the device. This is almost similiar to - * the interrupt service routine in the serial device. + * It is called if the data was received from the device. */ static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs) { + struct inbuf_t *inbuf = urb->context; + struct cardstate *cs = inbuf->cs; int resubmit = 0; int r; - struct cardstate *cs; unsigned numbytes; unsigned char *src; - //unsigned long flags; - struct inbuf_t *inbuf; - - IFNULLRET(urb); - inbuf = (struct inbuf_t *) urb->context; - IFNULLRET(inbuf); - //spin_lock_irqsave(&inbuf->lock, flags); - cs = inbuf->cs; - IFNULLGOTO(cs, exit); - IFNULLGOTO(cardstate, exit); - - if (!atomic_read(&cs->connected)) { - err("%s: disconnected", __func__); - goto exit; - } + unsigned long flags; if (!urb->status) { + if (!cs->connected) { + err("%s: disconnected", __func__); /* should never happen */ + return; + } + numbytes = urb->actual_length; if (numbytes) { src = inbuf->rcvbuf; if (unlikely(*src)) - warn("%s: There was no leading 0, but 0x%02x!", - __func__, (unsigned) *src); + dev_warn(cs->dev, + "%s: There was no leading 0, but 0x%02x!\n", + __func__, (unsigned) *src); ++src; /* skip leading 0x00 */ --numbytes; if (gigaset_fill_inbuf(inbuf, src, numbytes)) { - dbg(DEBUG_INTR, "%s-->BH", __func__); + gig_dbg(DEBUG_INTR, "%s-->BH", __func__); gigaset_schedule_event(inbuf->cs); } } else - dbg(DEBUG_INTR, "Received zero block length"); + gig_dbg(DEBUG_INTR, "Received zero block length"); resubmit = 1; } else { /* The urb might have been killed. */ - dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", - __func__, urb->status); - if (urb->status != -ENOENT) /* not killed */ + gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", + __func__, urb->status); + if (urb->status != -ENOENT) { /* not killed */ + if (!cs->connected) { + err("%s: disconnected", __func__); /* should never happen */ + return; + } resubmit = 1; + } } -exit: - //spin_unlock_irqrestore(&inbuf->lock, flags); + if (resubmit) { - r = usb_submit_urb(urb, SLAB_ATOMIC); + spin_lock_irqsave(&cs->lock, flags); + r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&cs->lock, flags); if (r) - err("error %d when resubmitting urb.", -r); + dev_err(cs->dev, "error %d when resubmitting urb.\n", + -r); } } -/* This callback routine is called when data was transmitted to a B-Channel. - * Therefore it has to check if there is still data to transmit. This - * happens by calling modem_fill via task queue. - * - */ +/* This callback routine is called when data was transmitted to the device. */ static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs) { - struct cardstate *cs = (struct cardstate *) urb->context; + struct cardstate *cs = urb->context; + unsigned long flags; - IFNULLRET(cs); -#ifdef CONFIG_GIGASET_DEBUG - if (!atomic_read(&cs->connected)) { - err("%s:not connected", __func__); - return; - } -#endif if (urb->status) - err("bulk transfer failed (status %d)", -urb->status); /* That's all we can do. Communication problems - are handeled by timeouts or network protocols */ + dev_err(cs->dev, "bulk transfer failed (status %d)\n", + -urb->status); + /* That's all we can do. Communication problems + are handled by timeouts or network protocols. */ - atomic_set(&cs->hw.usb->busy, 0); - tasklet_schedule(&cs->write_tasklet); + spin_lock_irqsave(&cs->lock, flags); + if (!cs->connected) { + err("%s: not connected", __func__); + } else { + atomic_set(&cs->hw.usb->busy, 0); + tasklet_schedule(&cs->write_tasklet); + } + spin_unlock_irqrestore(&cs->lock, flags); } static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) @@ -469,8 +456,8 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) spin_lock_irqsave(&cs->cmdlock, flags); cs->cmdbytes -= cs->curlen; - dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left", - cs->curlen, cs->cmdbytes); + gig_dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left", + cs->curlen, cs->cmdbytes); cs->cmdbuf = cb = cb->next; if (cb) { cb->prev = NULL; @@ -487,52 +474,51 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) } if (cb) { count = min(cb->len, ucs->bulk_out_size); + gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count); + usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_endpointAddr & 0x0f), - cb->buf + cb->offset, count, - gigaset_write_bulk_callback, cs); + usb_sndbulkpipe(ucs->udev, + ucs->bulk_out_endpointAddr & 0x0f), + cb->buf + cb->offset, count, + gigaset_write_bulk_callback, cs); cb->offset += count; cb->len -= count; atomic_set(&ucs->busy, 1); - dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count); - status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + spin_lock_irqsave(&cs->lock, flags); + status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&cs->lock, flags); + if (status) { atomic_set(&ucs->busy, 0); - err("could not submit urb (error %d).", + err("could not submit urb (error %d)\n", -status); - cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */ + cb->len = 0; /* skip urb => remove cb+wakeup + in next loop cycle */ } } - } while (cb && status); /* bei Fehler naechster Befehl //FIXME: ist das OK? */ + } while (cb && status); /* next command on error */ return status; } -/* Write string into transbuf and send it to modem. - */ +/* Send command to device. */ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, - int len, struct tasklet_struct *wake_tasklet) + int len, struct tasklet_struct *wake_tasklet) { struct cmdbuf_t *cb; unsigned long flags; gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", len, buf, 0); - - if (!atomic_read(&cs->connected)) { - err("%s: not connected", __func__); - return -ENODEV; - } + DEBUG_TRANSCMD : DEBUG_LOCKCMD, + "CMD Transmit", len, buf); if (len <= 0) return 0; if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { - err("%s: out of memory", __func__); + dev_err(cs->dev, "%s: out of memory\n", __func__); return -ENOMEM; } @@ -554,7 +540,10 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, cs->lastcmdbuf = cb; spin_unlock_irqrestore(&cs->cmdlock, flags); - tasklet_schedule(&cs->write_tasklet); + spin_lock_irqsave(&cs->lock, flags); + if (cs->connected) + tasklet_schedule(&cs->write_tasklet); + spin_unlock_irqrestore(&cs->lock, flags); return len; } @@ -578,11 +567,12 @@ static int gigaset_chars_in_buffer(struct cardstate *cs) static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) { #ifdef CONFIG_GIGASET_UNDOCREQ - gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf, 0); + struct usb_device *udev = cs->hw.usb->udev; + + gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf); memcpy(cs->hw.usb->bchars, buf, 6); - return usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41, - 0, 0, &buf, 6, 2000); + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, + 0, 0, &buf, 6, 2000); #else return -EINVAL; #endif @@ -604,7 +594,6 @@ static int gigaset_initbcshw(struct bc_state *bcs) if (!bcs->hw.usb) return 0; - //bcs->hw.usb->trans_flg = READY_TO_TRNSMIT; /* B-Channel ready to transmit */ return 1; } @@ -614,7 +603,6 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) static void gigaset_freecshw(struct cardstate *cs) { - //FIXME tasklet_kill(&cs->write_tasklet); kfree(cs->hw.usb); } @@ -639,33 +627,21 @@ static int gigaset_initcshw(struct cardstate *cs) //ucs->urb_cmd_out = NULL; ucs->read_urb = NULL; tasklet_init(&cs->write_tasklet, - &gigaset_modem_fill, (unsigned long) cs); + &gigaset_modem_fill, (unsigned long) cs); return 1; } -/* Writes the data of the current open skb into the modem. - * We have to protect against multiple calls until the - * callback handler () is called , due to the fact that we - * are just allowed to send data once to an endpoint. Therefore - * we using "trans_flg" to synchonize ... - */ +/* Send data from current skb to the device. */ static int write_modem(struct cardstate *cs) { - int ret; + int ret = 0; int count; struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ struct usb_cardstate *ucs = cs->hw.usb; - //unsigned long flags; - - IFNULLRETVAL(bcs->tx_skb, -EINVAL); - - dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); + unsigned long flags; - ret = -ENODEV; - IFNULLGOTO(ucs->bulk_out_buffer, error); - IFNULLGOTO(ucs->bulk_out_urb, error); - ret = 0; + gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); if (!bcs->tx_skb->len) { dev_kfree_skb_any(bcs->tx_skb); @@ -679,40 +655,42 @@ static int write_modem(struct cardstate *cs) count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count); skb_pull(bcs->tx_skb, count); - - usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_endpointAddr & 0x0f), - ucs->bulk_out_buffer, count, - gigaset_write_bulk_callback, cs); atomic_set(&ucs->busy, 1); - dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); + gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); + + spin_lock_irqsave(&cs->lock, flags); + if (cs->connected) { + usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, + usb_sndbulkpipe(ucs->udev, + ucs->bulk_out_endpointAddr & 0x0f), + ucs->bulk_out_buffer, count, + gigaset_write_bulk_callback, cs); + ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + } else { + ret = -ENODEV; + } + spin_unlock_irqrestore(&cs->lock, flags); - ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); if (ret) { - err("could not submit urb (error %d).", -ret); + err("could not submit urb (error %d)\n", -ret); atomic_set(&ucs->busy, 0); } + if (!bcs->tx_skb->len) { /* skb sent completely */ gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? - dbg(DEBUG_INTR, - "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb); + gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", + (unsigned long) bcs->tx_skb); dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; } return ret; -error: - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - return ret; - } static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id) + const struct usb_device_id *id) { int retval; struct usb_device *udev = interface_to_usbdev(interface); @@ -720,16 +698,14 @@ static int gigaset_probe(struct usb_interface *interface, struct usb_host_interface *hostif; struct cardstate *cs = NULL; struct usb_cardstate *ucs = NULL; - //struct usb_interface_descriptor *iface_desc; struct usb_endpoint_descriptor *endpoint; - //isdn_ctrl command; int buffer_size; int alt; - //unsigned long flags; - info("%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); + gig_dbg(DEBUG_ANY, + "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", + __func__, le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); retval = -ENODEV; //FIXME @@ -744,7 +720,7 @@ static int gigaset_probe(struct usb_interface *interface, ifnum = hostif->desc.bInterfaceNumber; // FIXME ? if (alt != 0 || ifnum != 0) { - warn("ifnum %d, alt %d", ifnum, alt); + dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt); return -ENODEV; } @@ -752,42 +728,29 @@ static int gigaset_probe(struct usb_interface *interface, * */ if (hostif->desc.bInterfaceClass != 255) { - info("%s: Device matched, but iface_desc[%d]->bInterfaceClass==%d !", - __func__, ifnum, hostif->desc.bInterfaceClass); + dev_info(&udev->dev, + "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n", + __func__, ifnum, hostif->desc.bInterfaceClass); return -ENODEV; } - info("%s: Device matched ... !", __func__); + dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); cs = gigaset_getunassignedcs(driver); if (!cs) { - warn("No free cardstate!"); + dev_warn(&udev->dev, "no free cardstate\n"); return -ENODEV; } ucs = cs->hw.usb; -#if 0 - if (usb_set_configuration(udev, udev->config[0].desc.bConfigurationValue) < 0) { - warn("set_configuration failed"); - goto error; - } - - - if (usb_set_interface(udev, ifnum/*==0*/, alt/*==0*/) < 0) { - warn("usb_set_interface failed, device %d interface %d altsetting %d", - udev->devnum, ifnum, alt); - goto error; - } -#endif + /* save off device structure ptrs for later use */ + usb_get_dev(udev); + ucs->udev = udev; + ucs->interface = interface; + cs->dev = &interface->dev; - /* set up the endpoint information */ - /* check out the endpoints */ - /* We will get 2 endpoints: One for sending commands to the device (bulk out) and one to - * poll messages from the device(int in). - * Therefore we will have an almost similiar situation as with our serial port handler. - * If an connection will be established, we will have to create data in/out pipes - * dynamically... - */ + /* save address of controller structure */ + usb_set_intfdata(interface, cs); // dev_set_drvdata(&interface->dev, cs); endpoint = &hostif->endpoint[0].desc; @@ -796,14 +759,14 @@ static int gigaset_probe(struct usb_interface *interface, ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress; ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!ucs->bulk_out_buffer) { - err("Couldn't allocate bulk_out_buffer"); + dev_err(cs->dev, "Couldn't allocate bulk_out_buffer\n"); retval = -ENOMEM; goto error; } ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->bulk_out_urb) { - err("Couldn't allocate bulk_out_buffer"); + dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n"); retval = -ENOMEM; goto error; } @@ -811,12 +774,10 @@ static int gigaset_probe(struct usb_interface *interface, endpoint = &hostif->endpoint[1].desc; atomic_set(&ucs->busy, 0); - ucs->udev = udev; - ucs->interface = interface; ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->read_urb) { - err("No free urbs available"); + dev_err(cs->dev, "No free urbs available\n"); retval = -ENOMEM; goto error; } @@ -825,38 +786,33 @@ static int gigaset_probe(struct usb_interface *interface, ucs->int_in_endpointAddr = endpoint->bEndpointAddress; cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL); if (!cs->inbuf[0].rcvbuf) { - err("Couldn't allocate rcvbuf"); + dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); retval = -ENOMEM; goto error; } /* Fill the interrupt urb and send it to the core */ usb_fill_int_urb(ucs->read_urb, udev, - usb_rcvintpipe(udev, - endpoint->bEndpointAddress & 0x0f), - cs->inbuf[0].rcvbuf, buffer_size, - gigaset_read_int_callback, - cs->inbuf + 0, endpoint->bInterval); + usb_rcvintpipe(udev, + endpoint->bEndpointAddress & 0x0f), + cs->inbuf[0].rcvbuf, buffer_size, + gigaset_read_int_callback, + cs->inbuf + 0, endpoint->bInterval); retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL); if (retval) { - err("Could not submit URB!"); + dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval); goto error; } /* tell common part that the device is ready */ if (startmode == SM_LOCKED) atomic_set(&cs->mstate, MS_LOCKED); + if (!gigaset_start(cs)) { tasklet_kill(&cs->write_tasklet); retval = -ENODEV; //FIXME goto error; } - - /* save address of controller structure */ - usb_set_intfdata(interface, cs); - - /* set up device sysfs */ - gigaset_init_dev_sysfs(interface); return 0; error: @@ -868,48 +824,45 @@ error: kfree(cs->inbuf[0].rcvbuf); if (ucs->read_urb != NULL) usb_free_urb(ucs->read_urb); + usb_set_intfdata(interface, NULL); ucs->read_urb = ucs->bulk_out_urb = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + usb_put_dev(ucs->udev); + ucs->udev = NULL; + ucs->interface = NULL; gigaset_unassign(cs); return retval; } -/** - * skel_disconnect - */ static void gigaset_disconnect(struct usb_interface *interface) { struct cardstate *cs; struct usb_cardstate *ucs; cs = usb_get_intfdata(interface); - - /* clear device sysfs */ - gigaset_free_dev_sysfs(interface); - - usb_set_intfdata(interface, NULL); ucs = cs->hw.usb; usb_kill_urb(ucs->read_urb); - //info("GigaSet USB device #%d will be disconnected", minor); gigaset_stop(cs); + usb_set_intfdata(interface, NULL); tasklet_kill(&cs->write_tasklet); - usb_kill_urb(ucs->bulk_out_urb); /* FIXME: nur, wenn noetig */ - //usb_kill_urb(ucs->urb_cmd_out); /* FIXME: nur, wenn noetig */ + usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ kfree(ucs->bulk_out_buffer); if (ucs->bulk_out_urb != NULL) usb_free_urb(ucs->bulk_out_urb); - //if(ucs->urb_cmd_out != NULL) - // usb_free_urb(ucs->urb_cmd_out); kfree(cs->inbuf[0].rcvbuf); if (ucs->read_urb != NULL) usb_free_urb(ucs->read_urb); - ucs->read_urb = ucs->bulk_out_urb/*=ucs->urb_cmd_out*/=NULL; + ucs->read_urb = ucs->bulk_out_urb = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + usb_put_dev(ucs->udev); + ucs->interface = NULL; + ucs->udev = NULL; + cs->dev = NULL; gigaset_unassign(cs); } @@ -942,9 +895,9 @@ static int __init usb_gigaset_init(void) /* allocate memory for our driver state and intialize it */ if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - GIGASET_DEVFSNAME, &ops, - THIS_MODULE)) == NULL) + GIGASET_MODULENAME, GIGASET_DEVNAME, + GIGASET_DEVFSNAME, &ops, + THIS_MODULE)) == NULL) goto error; /* allocate memory for our device state and intialize it */ @@ -981,8 +934,8 @@ error: if (cardstate) static void __exit usb_gigaset_exit(void) { gigaset_blockdriver(driver); /* => probe will fail - * => no gigaset_start any more - */ + * => no gigaset_start any more + */ gigaset_shutdown(cardstate); /* from now on, no isdn callback should be possible */ diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 2a2b03f..7bbfd85 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -51,8 +51,8 @@ MODULE_LICENSE("GPL"); handler. */ -static void avmcs_config(dev_link_t *link); -static void avmcs_release(dev_link_t *link); +static int avmcs_config(struct pcmcia_device *link); +static void avmcs_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -65,10 +65,10 @@ static void avmcs_detach(struct pcmcia_device *p_dev); /* A linked list of "instances" of the skeleton device. Each actual PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). + by one struct pcmcia_device structure (defined in ds.h). You may not want to use a linked list for this -- for example, the - memory card driver uses an array of dev_link_t pointers, where minor + memory card driver uses an array of struct pcmcia_device pointers, where minor device numbers are used to derive the corresponding array index. */ @@ -78,7 +78,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally can't be allocated dynamically. */ @@ -99,54 +99,38 @@ typedef struct local_info_t { ======================================================================*/ -static int avmcs_attach(struct pcmcia_device *p_dev) +static int avmcs_probe(struct pcmcia_device *p_dev) { - dev_link_t *link; local_info_t *local; - /* Initialize the dev_link_t structure */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) - goto err; - memset(link, 0, sizeof(struct dev_link_t)); - /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts2 = 0; + p_dev->io.NumPorts1 = 16; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.NumPorts2 = 0; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - /* General socket configuration */ - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.ConfigIndex = 1; - link->conf.Present = PRESENT_OPTION; + p_dev->conf.Attributes = CONF_ENABLE_IRQ; + p_dev->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.ConfigIndex = 1; + p_dev->conf.Present = PRESENT_OPTION; /* Allocate space for private device-specific data */ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) - goto err_kfree; + goto err; memset(local, 0, sizeof(local_info_t)); - link->priv = local; + p_dev->priv = local; - link->handle = p_dev; - p_dev->instance = link; + return avmcs_config(p_dev); - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - avmcs_config(link); - - return 0; - - err_kfree: - kfree(link); err: - return -EINVAL; + return -ENOMEM; } /* avmcs_attach */ /*====================================================================== @@ -158,15 +142,10 @@ static int avmcs_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void avmcs_detach(struct pcmcia_device *p_dev) +static void avmcs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - - if (link->state & DEV_CONFIG) avmcs_release(link); - - kfree(link->priv); - kfree(link); + kfree(link->priv); } /* avmcs_detach */ /*====================================================================== @@ -177,7 +156,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev) ======================================================================*/ -static int get_tuple(client_handle_t handle, tuple_t *tuple, +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_tuple_data(handle, tuple); @@ -185,7 +164,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_first_tuple(handle, tuple); @@ -193,7 +172,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_next_tuple(handle, tuple); @@ -201,9 +180,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void avmcs_config(dev_link_t *link) +static int avmcs_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; @@ -213,8 +191,7 @@ static void avmcs_config(dev_link_t *link) char devname[128]; int cardtype; int (*addcard)(unsigned int port, unsigned irq); - - handle = link->handle; + dev = link->priv; /* @@ -223,25 +200,21 @@ static void avmcs_config(dev_link_t *link) */ do { tuple.DesiredTuple = CISTPL_CONFIG; - i = pcmcia_get_first_tuple(handle, &tuple); + i = pcmcia_get_first_tuple(link, &tuple); if (i != CS_SUCCESS) break; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - i = pcmcia_get_tuple_data(handle, &tuple); + i = pcmcia_get_tuple_data(link, &tuple); if (i != CS_SUCCESS) break; - i = pcmcia_parse_tuple(handle, &tuple, &parse); + i = pcmcia_parse_tuple(link, &tuple, &parse); if (i != CS_SUCCESS) break; link->conf.ConfigBase = parse.config.base; } while (0); if (i != CS_SUCCESS) { - cs_error(link->handle, ParseTuple, i); - link->state &= ~DEV_CONFIG_PENDING; - return; + cs_error(link, ParseTuple, i); + return -ENODEV; } - - /* Configure card */ - link->state |= DEV_CONFIG; do { @@ -252,7 +225,7 @@ static void avmcs_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_VERS_1; devname[0] = 0; - if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) { + if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) { strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], sizeof(devname)); } @@ -263,7 +236,7 @@ static void avmcs_config(dev_link_t *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i == CS_SUCCESS) { if (cf->io.nwin > 0) { link->conf.ConfigIndex = cf->index; @@ -273,36 +246,36 @@ static void avmcs_config(dev_link_t *link) printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); break; } - + /* * allocate an interrupt line */ - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); - pcmcia_release_io(link->handle, &link->io); + cs_error(link, RequestIRQ, i); + /* undo */ + pcmcia_disable_device(link); break; } - + /* * configure the PCMCIA socket */ - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); + cs_error(link, RequestConfiguration, i); + pcmcia_disable_device(link); break; } @@ -331,13 +304,12 @@ found_port: dev->node.major = 64; dev->node.minor = 0; - link->dev = &dev->node; - - link->state &= ~DEV_CONFIG_PENDING; + link->dev_node = &dev->node; + /* If any step failed, release any partially configured state */ if (i != 0) { avmcs_release(link); - return; + return -ENODEV; } @@ -351,9 +323,10 @@ found_port: printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n", dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ); avmcs_release(link); - return; + return -ENODEV; } dev->node.minor = i; + return 0; } /* avmcs_config */ @@ -365,56 +338,12 @@ found_port: ======================================================================*/ -static void avmcs_release(dev_link_t *link) +static void avmcs_release(struct pcmcia_device *link) { - b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ); - - /* Unlink the device chain */ - link->dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ); + pcmcia_disable_device(link); } /* avmcs_release */ -static int avmcs_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int avmcs_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - -/*====================================================================== - - The card status event handler. Mostly, this schedules other - stuff to run after an event is received. A CARD_REMOVAL event - also sets some flags to discourage the net drivers from trying - to talk to the card any more. - - When a CARD_REMOVAL event is received, we immediately set a flag - to block future accesses to this device. All the functions that - actually access the device should check this flag to make sure - the card is still present. - -======================================================================*/ - static struct pcmcia_device_id avmcs_ids[] = { PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), @@ -429,11 +358,9 @@ static struct pcmcia_driver avmcs_driver = { .drv = { .name = "avm_cs", }, - .probe = avmcs_attach, + .probe = avmcs_probe, .remove = avmcs_detach, .id_table = avmcs_ids, - .suspend= avmcs_suspend, - .resume = avmcs_resume, }; static int __init avmcs_init(void) diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 969da40..ac28e32 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -67,8 +67,8 @@ module_param(isdnprot, int, 0); handler. */ -static void avma1cs_config(dev_link_t *link); -static void avma1cs_release(dev_link_t *link); +static int avma1cs_config(struct pcmcia_device *link); +static void avma1cs_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -82,10 +82,10 @@ static void avma1cs_detach(struct pcmcia_device *p_dev); /* A linked list of "instances" of the skeleton device. Each actual PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). + by one struct pcmcia_device structure (defined in ds.h). You may not want to use a linked list for this -- for example, the - memory card driver uses an array of dev_link_t pointers, where minor + memory card driver uses an array of struct pcmcia_device pointers, where minor device numbers are used to derive the corresponding array index. */ @@ -95,7 +95,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally can't be allocated dynamically. */ @@ -116,55 +116,40 @@ typedef struct local_info_t { ======================================================================*/ -static int avma1cs_attach(struct pcmcia_device *p_dev) +static int avma1cs_probe(struct pcmcia_device *p_dev) { - dev_link_t *link; local_info_t *local; DEBUG(0, "avma1cs_attach()\n"); - /* Initialize the dev_link_t structure */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) - return -ENOMEM; - memset(link, 0, sizeof(struct dev_link_t)); - /* Allocate space for private device-specific data */ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); - if (!local) { - kfree(link); + if (!local) return -ENOMEM; - } + memset(local, 0, sizeof(local_info_t)); - link->priv = local; + p_dev->priv = local; /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts2 = 16; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; - link->io.IOAddrLines = 5; + p_dev->io.NumPorts1 = 16; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.NumPorts2 = 16; + p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_16; + p_dev->io.IOAddrLines = 5; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; /* General socket configuration */ - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.ConfigIndex = 1; - link->conf.Present = PRESENT_OPTION; + p_dev->conf.Attributes = CONF_ENABLE_IRQ; + p_dev->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.ConfigIndex = 1; + p_dev->conf.Present = PRESENT_OPTION; - link->handle = p_dev; - p_dev->instance = link; - - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - avma1cs_config(link); - - return 0; + return avma1cs_config(p_dev); } /* avma1cs_attach */ /*====================================================================== @@ -176,17 +161,11 @@ static int avma1cs_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void avma1cs_detach(struct pcmcia_device *p_dev) +static void avma1cs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - - DEBUG(0, "avma1cs_detach(0x%p)\n", link); - - if (link->state & DEV_CONFIG) - avma1cs_release(link); - - kfree(link->priv); - kfree(link); + DEBUG(0, "avma1cs_detach(0x%p)\n", link); + avma1cs_release(link); + kfree(link->priv); } /* avma1cs_detach */ /*====================================================================== @@ -197,7 +176,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev) ======================================================================*/ -static int get_tuple(client_handle_t handle, tuple_t *tuple, +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_tuple_data(handle, tuple); @@ -205,7 +184,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_first_tuple(handle, tuple); @@ -213,7 +192,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_next_tuple(handle, tuple); @@ -221,9 +200,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void avma1cs_config(dev_link_t *link) +static int avma1cs_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; @@ -233,8 +211,7 @@ static void avma1cs_config(dev_link_t *link) char devname[128]; IsdnCard_t icard; int busy = 0; - - handle = link->handle; + dev = link->priv; DEBUG(0, "avma1cs_config(0x%p)\n", link); @@ -245,25 +222,21 @@ static void avma1cs_config(dev_link_t *link) */ do { tuple.DesiredTuple = CISTPL_CONFIG; - i = pcmcia_get_first_tuple(handle, &tuple); + i = pcmcia_get_first_tuple(link, &tuple); if (i != CS_SUCCESS) break; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - i = pcmcia_get_tuple_data(handle, &tuple); + i = pcmcia_get_tuple_data(link, &tuple); if (i != CS_SUCCESS) break; - i = pcmcia_parse_tuple(handle, &tuple, &parse); + i = pcmcia_parse_tuple(link, &tuple, &parse); if (i != CS_SUCCESS) break; link->conf.ConfigBase = parse.config.base; } while (0); if (i != CS_SUCCESS) { - cs_error(link->handle, ParseTuple, i); - link->state &= ~DEV_CONFIG_PENDING; - return; + cs_error(link, ParseTuple, i); + return -ENODEV; } - - /* Configure card */ - link->state |= DEV_CONFIG; do { @@ -274,7 +247,7 @@ static void avma1cs_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_VERS_1; devname[0] = 0; - if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) { + if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) { strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], sizeof(devname)); } @@ -285,7 +258,7 @@ static void avma1cs_config(dev_link_t *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i == CS_SUCCESS) { if (cf->io.nwin > 0) { link->conf.ConfigIndex = cf->index; @@ -295,36 +268,36 @@ static void avma1cs_config(dev_link_t *link) printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1 - 1); - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); break; } /* * allocate an interrupt line */ - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); - pcmcia_release_io(link->handle, &link->io); + cs_error(link, RequestIRQ, i); + /* undo */ + pcmcia_disable_device(link); break; } - + /* * configure the PCMCIA socket */ - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); + cs_error(link, RequestConfiguration, i); + pcmcia_disable_device(link); break; } @@ -336,13 +309,12 @@ found_port: strcpy(dev->node.dev_name, "A1"); dev->node.major = 45; dev->node.minor = 0; - link->dev = &dev->node; - - link->state &= ~DEV_CONFIG_PENDING; + link->dev_node = &dev->node; + /* If any step failed, release any partially configured state */ if (i != 0) { avma1cs_release(link); - return; + return -ENODEV; } printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n", @@ -357,10 +329,11 @@ found_port: if (i < 0) { printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); avma1cs_release(link); - return; + return -ENODEV; } dev->node.minor = i; + return 0; } /* avma1cs_config */ /*====================================================================== @@ -371,47 +344,18 @@ found_port: ======================================================================*/ -static void avma1cs_release(dev_link_t *link) +static void avma1cs_release(struct pcmcia_device *link) { - local_info_t *local = link->priv; + local_info_t *local = link->priv; - DEBUG(0, "avma1cs_release(0x%p)\n", link); + DEBUG(0, "avma1cs_release(0x%p)\n", link); - /* no unregister function with hisax */ - HiSax_closecard(local->node.minor); + /* now unregister function with hisax */ + HiSax_closecard(local->node.minor); - /* Unlink the device chain */ - link->dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link); } /* avma1cs_release */ -static int avma1cs_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int avma1cs_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - static struct pcmcia_device_id avma1cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb), @@ -425,13 +369,11 @@ static struct pcmcia_driver avma1cs_driver = { .drv = { .name = "avma1_cs", }, - .probe = avma1cs_attach, + .probe = avma1cs_probe, .remove = avma1cs_detach, .id_table = avma1cs_ids, - .suspend = avma1cs_suspend, - .resume = avma1cs_resume, }; - + /*====================================================================*/ static int __init init_avma1_cs(void) diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 062fb8f..e18e75b 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -94,8 +94,8 @@ module_param(protocol, int, 0); handler. */ -static void elsa_cs_config(dev_link_t *link); -static void elsa_cs_release(dev_link_t *link); +static int elsa_cs_config(struct pcmcia_device *link); +static void elsa_cs_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -111,7 +111,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally shouldn't be allocated dynamically. In this case, we also provide a flag to indicate if a device is @@ -121,7 +121,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev); */ typedef struct local_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; int busy; int cardnr; @@ -139,9 +139,8 @@ typedef struct local_info_t { ======================================================================*/ -static int elsa_cs_attach(struct pcmcia_device *p_dev) +static int elsa_cs_probe(struct pcmcia_device *link) { - dev_link_t *link; local_info_t *local; DEBUG(0, "elsa_cs_attach()\n"); @@ -150,8 +149,11 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev) local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; memset(local, 0, sizeof(local_info_t)); + + local->p_dev = link; + link->priv = local; + local->cardnr = -1; - link = &local->link; link->priv = local; /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; @@ -170,16 +172,9 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev) link->io.IOAddrLines = 3; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - elsa_cs_config(link); - - return 0; + return elsa_cs_config(link); } /* elsa_cs_attach */ /*====================================================================== @@ -191,20 +186,16 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void elsa_cs_detach(struct pcmcia_device *p_dev) +static void elsa_cs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - local_info_t *info = link->priv; + local_info_t *info = link->priv; - DEBUG(0, "elsa_cs_detach(0x%p)\n", link); + DEBUG(0, "elsa_cs_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) { - info->busy = 1; - elsa_cs_release(link); - } - - kfree(info); + info->busy = 1; + elsa_cs_release(link); + kfree(info); } /* elsa_cs_detach */ /*====================================================================== @@ -214,7 +205,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev) device available to the system. ======================================================================*/ -static int get_tuple(client_handle_t handle, tuple_t *tuple, +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_tuple_data(handle, tuple); @@ -222,7 +213,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_first_tuple(handle, tuple); @@ -230,7 +221,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_next_tuple(handle, tuple); @@ -238,9 +229,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void elsa_cs_config(dev_link_t *link) +static int elsa_cs_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; local_info_t *dev; @@ -250,7 +240,6 @@ static void elsa_cs_config(dev_link_t *link) IsdnCard_t icard; DEBUG(0, "elsa_config(0x%p)\n", link); - handle = link->handle; dev = link->priv; /* @@ -262,7 +251,7 @@ static void elsa_cs_config(dev_link_t *link) tuple.TupleDataMax = 255; tuple.TupleOffset = 0; tuple.Attributes = 0; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); if (i != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -270,32 +259,29 @@ static void elsa_cs_config(dev_link_t *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i == CS_SUCCESS) { if ( (cf->io.nwin > 0) && cf->io.win[0].base) { printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n"); link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } else { printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n"); link->conf.ConfigIndex = cf->index; for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { link->io.BasePort1 = j; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } break; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } if (i != CS_SUCCESS) { @@ -303,14 +289,14 @@ static void elsa_cs_config(dev_link_t *link) goto cs_failed; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { link->irq.AssignedIRQ = 0; last_fn = RequestIRQ; goto cs_failed; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { last_fn = RequestConfiguration; goto cs_failed; @@ -321,14 +307,11 @@ static void elsa_cs_config(dev_link_t *link) sprintf(dev->node.dev_name, "elsa"); dev->node.major = dev->node.minor = 0x0; - link->dev = &dev->node; + link->dev_node = &dev->node; /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(KERN_INFO "%s: index 0x%02x: ", + dev->node.dev_name, link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) @@ -339,8 +322,6 @@ static void elsa_cs_config(dev_link_t *link) link->io.BasePort2+link->io.NumPorts2-1); printk("\n"); - link->state &= ~DEV_CONFIG_PENDING; - icard.para[0] = link->irq.AssignedIRQ; icard.para[1] = link->io.BasePort1; icard.protocol = protocol; @@ -354,10 +335,11 @@ static void elsa_cs_config(dev_link_t *link) } else ((local_info_t*)link->priv)->cardnr = i; - return; + return 0; cs_failed: - cs_error(link->handle, last_fn, i); + cs_error(link, last_fn, i); elsa_cs_release(link); + return -ENODEV; } /* elsa_cs_config */ /*====================================================================== @@ -368,7 +350,7 @@ cs_failed: ======================================================================*/ -static void elsa_cs_release(dev_link_t *link) +static void elsa_cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; @@ -380,39 +362,23 @@ static void elsa_cs_release(dev_link_t *link) HiSax_closecard(local->cardnr); } } - /* Unlink the device chain */ - link->dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - if (link->win) - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + + pcmcia_disable_device(link); } /* elsa_cs_release */ -static int elsa_suspend(struct pcmcia_device *p_dev) +static int elsa_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state |= DEV_SUSPEND; dev->busy = 1; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); return 0; } -static int elsa_resume(struct pcmcia_device *p_dev) +static int elsa_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); dev->busy = 0; return 0; @@ -430,7 +396,7 @@ static struct pcmcia_driver elsa_cs_driver = { .drv = { .name = "elsa_cs", }, - .probe = elsa_cs_attach, + .probe = elsa_cs_probe, .remove = elsa_cs_detach, .id_table = elsa_ids, .suspend = elsa_suspend, diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 6f5213a..9bb18f3 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -95,8 +95,8 @@ module_param(protocol, int, 0); event handler. */ -static void sedlbauer_config(dev_link_t *link); -static void sedlbauer_release(dev_link_t *link); +static int sedlbauer_config(struct pcmcia_device *link); +static void sedlbauer_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -119,7 +119,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally shouldn't be allocated dynamically. @@ -130,7 +130,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev); */ typedef struct local_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; int stop; int cardnr; @@ -148,11 +148,10 @@ typedef struct local_info_t { ======================================================================*/ -static int sedlbauer_attach(struct pcmcia_device *p_dev) +static int sedlbauer_probe(struct pcmcia_device *link) { local_info_t *local; - dev_link_t *link; - + DEBUG(0, "sedlbauer_attach()\n"); /* Allocate space for private device-specific data */ @@ -160,8 +159,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) if (!local) return -ENOMEM; memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; - link = &local->link; link->priv = local; - + + local->p_dev = link; + link->priv = local; + /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; @@ -182,18 +183,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.IOAddrLines = 3; - link->conf.Attributes = 0; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - sedlbauer_config(link); - - return 0; + return sedlbauer_config(link); } /* sedlbauer_attach */ /*====================================================================== @@ -205,19 +198,15 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void sedlbauer_detach(struct pcmcia_device *p_dev) +static void sedlbauer_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - - DEBUG(0, "sedlbauer_detach(0x%p)\n", link); + DEBUG(0, "sedlbauer_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) { - ((local_info_t *)link->priv)->stop = 1; - sedlbauer_release(link); - } + ((local_info_t *)link->priv)->stop = 1; + sedlbauer_release(link); - /* This points to the parent local_info_t struct */ - kfree(link->priv); + /* This points to the parent local_info_t struct */ + kfree(link->priv); } /* sedlbauer_detach */ /*====================================================================== @@ -230,9 +219,8 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void sedlbauer_config(dev_link_t *link) +static int sedlbauer_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; local_info_t *dev = link->priv; tuple_t tuple; cisparse_t parse; @@ -254,18 +242,13 @@ static void sedlbauer_config(dev_link_t *link) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; - /* Look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); /* In this loop, we scan the CIS for configuration table entries, @@ -280,12 +263,12 @@ static void sedlbauer_config(dev_link_t *link) will only use the CIS to fill in implementation-defined details. */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; @@ -309,10 +292,10 @@ static void sedlbauer_config(dev_link_t *link) } if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; /* Do we need to allocate an interrupt? */ @@ -339,13 +322,13 @@ static void sedlbauer_config(dev_link_t *link) link->io.NumPorts2 = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; } /* Now set up a common memory window, if needed. There is room - in the dev_link_t structure for one memory window handle, + in the struct pcmcia_device structure for one memory window handle, but if the base addresses need to be saved, or if multiple windows are needed, the info should go in the private data structure for this device. @@ -366,7 +349,7 @@ static void sedlbauer_config(dev_link_t *link) req.Size = 0x1000; */ req.AccessSpeed = 0; - if (pcmcia_request_window(&link->handle, &req, &link->win) != 0) + if (pcmcia_request_window(&link, &req, &link->win) != 0) goto next_entry; map.Page = 0; map.CardOffset = mem->win[0].card_addr; if (pcmcia_map_mem_page(link->win, &map) != 0) @@ -374,29 +357,25 @@ static void sedlbauer_config(dev_link_t *link) } /* If we got this far, we're cool! */ break; - + next_entry: -/* new in dummy.cs 2001/01/28 MN - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); -*/ - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } - + /* Allocate an interrupt line. Note that this does not assign a handler to the interrupt, unless the 'Handler' member of the irq structure is initialized. */ if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* At this point, the dev_node_t structure(s) need to be @@ -404,14 +383,13 @@ static void sedlbauer_config(dev_link_t *link) */ sprintf(dev->node.dev_name, "sedlbauer"); dev->node.major = dev->node.minor = 0; - link->dev = &dev->node; + link->dev_node = &dev->node; /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(KERN_INFO "%s: index 0x%02x:", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Vpp) + printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) @@ -424,8 +402,6 @@ static void sedlbauer_config(dev_link_t *link) printk(", mem 0x%06lx-0x%06lx", req.Base, req.Base+req.Size-1); printk("\n"); - - link->state &= ~DEV_CONFIG_PENDING; icard.para[0] = link->irq.AssignedIRQ; icard.para[1] = link->io.BasePort1; @@ -437,14 +413,16 @@ static void sedlbauer_config(dev_link_t *link) printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", last_ret, link->io.BasePort1); sedlbauer_release(link); + return -ENODEV; } else ((local_info_t*)link->priv)->cardnr = last_ret; - return; + return 0; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); sedlbauer_release(link); + return -ENODEV; } /* sedlbauer_config */ @@ -456,7 +434,7 @@ cs_failed: ======================================================================*/ -static void sedlbauer_release(dev_link_t *link) +static void sedlbauer_release(struct pcmcia_device *link) { local_info_t *local = link->priv; DEBUG(0, "sedlbauer_release(0x%p)\n", link); @@ -467,46 +445,23 @@ static void sedlbauer_release(dev_link_t *link) HiSax_closecard(local->cardnr); } } - /* Unlink the device chain */ - link->dev = NULL; - /* - In a normal driver, additional code may be needed to release - other kernel data structures associated with this device. - */ - - /* Don't bother checking to see if these succeed or not */ - if (link->win) - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link); } /* sedlbauer_release */ -static int sedlbauer_suspend(struct pcmcia_device *p_dev) +static int sedlbauer_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state |= DEV_SUSPEND; dev->stop = 1; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); return 0; } -static int sedlbauer_resume(struct pcmcia_device *p_dev) +static int sedlbauer_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); dev->stop = 0; return 0; @@ -530,7 +485,7 @@ static struct pcmcia_driver sedlbauer_driver = { .drv = { .name = "sedlbauer_cs", }, - .probe = sedlbauer_attach, + .probe = sedlbauer_probe, .remove = sedlbauer_detach, .id_table = sedlbauer_ids, .suspend = sedlbauer_suspend, diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 4e5c14c..afcc2ae 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -75,8 +75,8 @@ module_param(protocol, int, 0); handler. */ -static void teles_cs_config(dev_link_t *link); -static void teles_cs_release(dev_link_t *link); +static int teles_cs_config(struct pcmcia_device *link); +static void teles_cs_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -89,10 +89,10 @@ static void teles_detach(struct pcmcia_device *p_dev); /* A linked list of "instances" of the teles_cs device. Each actual PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). + by one struct pcmcia_device structure (defined in ds.h). You may not want to use a linked list for this -- for example, the - memory card driver uses an array of dev_link_t pointers, where minor + memory card driver uses an array of struct pcmcia_device pointers, where minor device numbers are used to derive the corresponding array index. */ @@ -102,7 +102,7 @@ static void teles_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally shouldn't be allocated dynamically. In this case, we also provide a flag to indicate if a device is @@ -112,7 +112,7 @@ static void teles_detach(struct pcmcia_device *p_dev); */ typedef struct local_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; int busy; int cardnr; @@ -130,9 +130,8 @@ typedef struct local_info_t { ======================================================================*/ -static int teles_attach(struct pcmcia_device *p_dev) +static int teles_probe(struct pcmcia_device *link) { - dev_link_t *link; local_info_t *local; DEBUG(0, "teles_attach()\n"); @@ -142,7 +141,9 @@ static int teles_attach(struct pcmcia_device *p_dev) if (!local) return -ENOMEM; memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; - link = &local->link; link->priv = local; + + local->p_dev = link; + link->priv = local; /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; @@ -161,16 +162,9 @@ static int teles_attach(struct pcmcia_device *p_dev) link->io.IOAddrLines = 5; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - teles_cs_config(link); - - return 0; + return teles_cs_config(link); } /* teles_attach */ /*====================================================================== @@ -182,20 +176,16 @@ static int teles_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void teles_detach(struct pcmcia_device *p_dev) +static void teles_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - local_info_t *info = link->priv; - - DEBUG(0, "teles_detach(0x%p)\n", link); + local_info_t *info = link->priv; - if (link->state & DEV_CONFIG) { - info->busy = 1; - teles_cs_release(link); - } + DEBUG(0, "teles_detach(0x%p)\n", link); - kfree(info); + info->busy = 1; + teles_cs_release(link); + kfree(info); } /* teles_detach */ /*====================================================================== @@ -205,7 +195,7 @@ static void teles_detach(struct pcmcia_device *p_dev) device available to the system. ======================================================================*/ -static int get_tuple(client_handle_t handle, tuple_t *tuple, +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_tuple_data(handle, tuple); @@ -213,7 +203,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_first_tuple(handle, tuple); @@ -221,7 +211,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_next_tuple(handle, tuple); @@ -229,9 +219,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void teles_cs_config(dev_link_t *link) +static int teles_cs_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; local_info_t *dev; @@ -241,7 +230,6 @@ static void teles_cs_config(dev_link_t *link) IsdnCard_t icard; DEBUG(0, "teles_config(0x%p)\n", link); - handle = link->handle; dev = link->priv; /* @@ -253,7 +241,7 @@ static void teles_cs_config(dev_link_t *link) tuple.TupleDataMax = 255; tuple.TupleOffset = 0; tuple.Attributes = 0; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); if (i != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -261,32 +249,29 @@ static void teles_cs_config(dev_link_t *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i == CS_SUCCESS) { if ( (cf->io.nwin > 0) && cf->io.win[0].base) { printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } else { printk(KERN_INFO "(teles_cs: looks like the 97 model)\n"); link->conf.ConfigIndex = cf->index; for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { link->io.BasePort1 = j; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } break; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } if (i != CS_SUCCESS) { @@ -294,14 +279,14 @@ static void teles_cs_config(dev_link_t *link) goto cs_failed; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { link->irq.AssignedIRQ = 0; last_fn = RequestIRQ; goto cs_failed; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { last_fn = RequestConfiguration; goto cs_failed; @@ -312,14 +297,11 @@ static void teles_cs_config(dev_link_t *link) sprintf(dev->node.dev_name, "teles"); dev->node.major = dev->node.minor = 0x0; - link->dev = &dev->node; + link->dev_node = &dev->node; /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(KERN_INFO "%s: index 0x%02x:", + dev->node.dev_name, link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) @@ -330,8 +312,6 @@ static void teles_cs_config(dev_link_t *link) link->io.BasePort2+link->io.NumPorts2-1); printk("\n"); - link->state &= ~DEV_CONFIG_PENDING; - icard.para[0] = link->irq.AssignedIRQ; icard.para[1] = link->io.BasePort1; icard.protocol = protocol; @@ -342,13 +322,16 @@ static void teles_cs_config(dev_link_t *link) printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); teles_cs_release(link); - } else - ((local_info_t*)link->priv)->cardnr = i; + return -ENODEV; + } + + ((local_info_t*)link->priv)->cardnr = i; + return 0; - return; cs_failed: - cs_error(link->handle, last_fn, i); + cs_error(link, last_fn, i); teles_cs_release(link); + return -ENODEV; } /* teles_cs_config */ /*====================================================================== @@ -359,7 +342,7 @@ cs_failed: ======================================================================*/ -static void teles_cs_release(dev_link_t *link) +static void teles_cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; @@ -371,39 +354,23 @@ static void teles_cs_release(dev_link_t *link) HiSax_closecard(local->cardnr); } } - /* Unlink the device chain */ - link->dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - if (link->win) - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + + pcmcia_disable_device(link); } /* teles_cs_release */ -static int teles_suspend(struct pcmcia_device *p_dev) +static int teles_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state |= DEV_SUSPEND; dev->busy = 1; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); return 0; } -static int teles_resume(struct pcmcia_device *p_dev) +static int teles_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); dev->busy = 0; return 0; @@ -421,7 +388,7 @@ static struct pcmcia_driver teles_cs_driver = { .drv = { .name = "teles_cs", }, - .probe = teles_attach, + .probe = teles_probe, .remove = teles_detach, .id_table = teles_ids, .suspend = teles_suspend, diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index a0927d1..9187422 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -109,7 +109,7 @@ isdn_ppp_free(isdn_net_local * lp) { struct ippp_struct *is; - if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { + if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: ppp_slot(%d) out of range\n", __FUNCTION__, lp->ppp_slot); return 0; @@ -126,7 +126,7 @@ isdn_ppp_free(isdn_net_local * lp) lp->netdev->pb->ref_ct--; spin_unlock(&lp->netdev->pb->lock); #endif /* CONFIG_ISDN_MPP */ - if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { + if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n", __FUNCTION__, lp->ppp_slot); return 0; @@ -279,7 +279,7 @@ isdn_ppp_open(int min, struct file *file) int slot; struct ippp_struct *is; - if (min < 0 || min > ISDN_MAX_CHANNELS) + if (min < 0 || min >= ISDN_MAX_CHANNELS) return -ENODEV; slot = isdn_ppp_get_slot(); @@ -1042,7 +1042,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff if (lp->master) { // FIXME? mlp = (isdn_net_local *) lp->master->priv; slot = mlp->ppp_slot; - if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n", lp->ppp_slot); goto drop_packet; @@ -1264,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) /* we have our lp locked from now on */ slot = lp->ppp_slot; - if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n", lp->ppp_slot); kfree_skb(skb); @@ -1603,7 +1603,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, mp = net_dev->pb; stats = &mp->stats; slot = lp->ppp_slot; - if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: lp->ppp_slot(%d)\n", __FUNCTION__, lp->ppp_slot); stats->frame_drops++; @@ -1640,7 +1640,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, is->last_link_seqno = minseq = newseq; for (lpq = net_dev->queue;;) { slot = lpq->ppp_slot; - if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n", __FUNCTION__, lpq->ppp_slot); } else { @@ -2648,7 +2648,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n", lp->ppp_slot); - if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { + if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", __FUNCTION__, lp->ppp_slot); return; @@ -2658,7 +2658,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, if(lp->master) { int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot; - if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: slot(%d) out of range\n", __FUNCTION__, slot); return; @@ -2845,7 +2845,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct if (lp->master) { slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot; - if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: slot(%d) out of range\n", __FUNCTION__, slot); return; |