Commit 7ecc59c1 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

parents bcdce719 1cec9727
...@@ -60,10 +60,9 @@ open() operation on regular files or character devices. ...@@ -60,10 +60,9 @@ open() operation on regular files or character devices.
After a successful return from register_appl(), CAPI messages from the After a successful return from register_appl(), CAPI messages from the
application may be passed to the driver for the device via calls to the application may be passed to the driver for the device via calls to the
send_message() callback function. The CAPI message to send is stored in the send_message() callback function. Conversely, the driver may call Kernel
data portion of an skb. Conversely, the driver may call Kernel CAPI's CAPI's capi_ctr_handle_message() function to pass a received CAPI message to
capi_ctr_handle_message() function to pass a received CAPI message to Kernel Kernel CAPI for forwarding to an application, specifying its ApplID.
CAPI for forwarding to an application, specifying its ApplID.
Deregistration requests (CAPI operation CAPI_RELEASE) from applications are Deregistration requests (CAPI operation CAPI_RELEASE) from applications are
forwarded as calls to the release_appl() callback function, passing the same forwarded as calls to the release_appl() callback function, passing the same
...@@ -142,6 +141,7 @@ u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb) ...@@ -142,6 +141,7 @@ u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb)
to accepting or queueing the message. Errors occurring during the to accepting or queueing the message. Errors occurring during the
actual processing of the message should be signaled with an actual processing of the message should be signaled with an
appropriate reply message. appropriate reply message.
May be called in process or interrupt context.
Calls to this function are not serialized by Kernel CAPI, ie. it must Calls to this function are not serialized by Kernel CAPI, ie. it must
be prepared to be re-entered. be prepared to be re-entered.
...@@ -154,7 +154,8 @@ read_proc_t *ctr_read_proc ...@@ -154,7 +154,8 @@ read_proc_t *ctr_read_proc
system entry, /proc/capi/controllers/<n>; will be called with a system entry, /proc/capi/controllers/<n>; will be called with a
pointer to the device's capi_ctr structure as the last (data) argument pointer to the device's capi_ctr structure as the last (data) argument
Note: Callback functions are never called in interrupt context. Note: Callback functions except send_message() are never called in interrupt
context.
- to be filled in before calling capi_ctr_ready(): - to be filled in before calling capi_ctr_ready():
...@@ -171,14 +172,40 @@ u8 serial[CAPI_SERIAL_LEN] ...@@ -171,14 +172,40 @@ u8 serial[CAPI_SERIAL_LEN]
value to return for CAPI_GET_SERIAL value to return for CAPI_GET_SERIAL
4.3 The _cmsg Structure 4.3 SKBs
CAPI messages are passed between Kernel CAPI and the driver via send_message()
and capi_ctr_handle_message(), stored in the data portion of a socket buffer
(skb). Each skb contains a single CAPI message coded according to the CAPI 2.0
standard.
For the data transfer messages, DATA_B3_REQ and DATA_B3_IND, the actual
payload data immediately follows the CAPI message itself within the same skb.
The Data and Data64 parameters are not used for processing. The Data64
parameter may be omitted by setting the length field of the CAPI message to 22
instead of 30.
4.4 The _cmsg Structure
(declared in <linux/isdn/capiutil.h>) (declared in <linux/isdn/capiutil.h>)
The _cmsg structure stores the contents of a CAPI 2.0 message in an easily The _cmsg structure stores the contents of a CAPI 2.0 message in an easily
accessible form. It contains members for all possible CAPI 2.0 parameters, of accessible form. It contains members for all possible CAPI 2.0 parameters,
which only those appearing in the message type currently being processed are including subparameters of the Additional Info and B Protocol structured
actually used. Unused members should be set to zero. parameters, with the following exceptions:
* second Calling party number (CONNECT_IND)
* Data64 (DATA_B3_REQ and DATA_B3_IND)
* Sending complete (subparameter of Additional Info, CONNECT_REQ and INFO_REQ)
* Global Configuration (subparameter of B Protocol, CONNECT_REQ, CONNECT_RESP
and SELECT_B_PROTOCOL_REQ)
Only those parameters appearing in the message type currently being processed
are actually used. Unused members should be set to zero.
Members are named after the CAPI 2.0 standard names of the parameters they Members are named after the CAPI 2.0 standard names of the parameters they
represent. See <linux/isdn/capiutil.h> for the exact spelling. Member data represent. See <linux/isdn/capiutil.h> for the exact spelling. Member data
...@@ -190,18 +217,19 @@ u16 for CAPI parameters of type 'word' ...@@ -190,18 +217,19 @@ u16 for CAPI parameters of type 'word'
u32 for CAPI parameters of type 'dword' u32 for CAPI parameters of type 'dword'
_cstruct for CAPI parameters of type 'struct' not containing any _cstruct for CAPI parameters of type 'struct'
variably-sized (struct) subparameters (eg. 'Called Party Number')
The member is a pointer to a buffer containing the parameter in The member is a pointer to a buffer containing the parameter in
CAPI encoding (length + content). It may also be NULL, which will CAPI encoding (length + content). It may also be NULL, which will
be taken to represent an empty (zero length) parameter. be taken to represent an empty (zero length) parameter.
Subparameters are stored in encoded form within the content part.
_cmstruct for CAPI parameters of type 'struct' containing 'struct' _cmstruct alternative representation for CAPI parameters of type 'struct'
subparameters ('Additional Info' and 'B Protocol') (used only for the 'Additional Info' and 'B Protocol' parameters)
The representation is a single byte containing one of the values: The representation is a single byte containing one of the values:
CAPI_DEFAULT: the parameter is empty CAPI_DEFAULT: The parameter is empty/absent.
CAPI_COMPOSE: the values of the subparameters are stored CAPI_COMPOSE: The parameter is present.
individually in the corresponding _cmsg structure members Subparameter values are stored individually in the corresponding
_cmsg structure members.
Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert
messages between their transport encoding described in the CAPI 2.0 standard messages between their transport encoding described in the CAPI 2.0 standard
...@@ -297,3 +325,26 @@ char *capi_cmd2str(u8 Command, u8 Subcommand) ...@@ -297,3 +325,26 @@ char *capi_cmd2str(u8 Command, u8 Subcommand)
be NULL if the command/subcommand is not one of those defined in the be NULL if the command/subcommand is not one of those defined in the
CAPI 2.0 standard. CAPI 2.0 standard.
7. Debugging
The module kernelcapi has a module parameter showcapimsgs controlling some
debugging output produced by the module. It can only be set when the module is
loaded, via a parameter "showcapimsgs=<n>" to the modprobe command, either on
the command line or in the configuration file.
If the lowest bit of showcapimsgs is set, kernelcapi logs controller and
application up and down events.
In addition, every registered CAPI controller has an associated traceflag
parameter controlling how CAPI messages sent from and to tha controller are
logged. The traceflag parameter is initialized with the value of the
showcapimsgs parameter when the controller is registered, but can later be
changed via the MANUFACTURER_REQ command KCAPI_CMD_TRACE.
If the value of traceflag is non-zero, CAPI messages are logged.
DATA_B3 messages are only logged if the value of traceflag is > 2.
If the lowest bit of traceflag is set, only the command/subcommand and message
length are logged. Otherwise, kernelcapi logs a readable representation of
the entire message.
...@@ -90,6 +90,11 @@ Examples: ...@@ -90,6 +90,11 @@ Examples:
pgset "dstmac 00:00:00:00:00:00" sets MAC destination address pgset "dstmac 00:00:00:00:00:00" sets MAC destination address
pgset "srcmac 00:00:00:00:00:00" sets MAC source address pgset "srcmac 00:00:00:00:00:00" sets MAC source address
pgset "queue_map_min 0" Sets the min value of tx queue interval
pgset "queue_map_max 7" Sets the max value of tx queue interval, for multiqueue devices
To select queue 1 of a given device,
use queue_map_min=1 and queue_map_max=1
pgset "src_mac_count 1" Sets the number of MACs we'll range through. pgset "src_mac_count 1" Sets the number of MACs we'll range through.
The 'minimum' MAC is what you set with srcmac. The 'minimum' MAC is what you set with srcmac.
...@@ -101,6 +106,9 @@ Examples: ...@@ -101,6 +106,9 @@ Examples:
IPDST_RND, UDPSRC_RND, IPDST_RND, UDPSRC_RND,
UDPDST_RND, MACSRC_RND, MACDST_RND UDPDST_RND, MACSRC_RND, MACDST_RND
MPLS_RND, VID_RND, SVID_RND MPLS_RND, VID_RND, SVID_RND
QUEUE_MAP_RND # queue map random
QUEUE_MAP_CPU # queue map mirrors smp_processor_id()
pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then
cycle through the port range. cycle through the port range.
......
...@@ -227,7 +227,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) ...@@ -227,7 +227,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
* cn_proc_mcast_ctl * cn_proc_mcast_ctl
* @data: message sent from userspace via the connector * @data: message sent from userspace via the connector
*/ */
static void cn_proc_mcast_ctl(struct cn_msg *msg) static void cn_proc_mcast_ctl(struct cn_msg *msg,
struct netlink_skb_parms *nsp)
{ {
enum proc_cn_mcast_op *mc_op = NULL; enum proc_cn_mcast_op *mc_op = NULL;
int err = 0; int err = 0;
......
...@@ -603,7 +603,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) ...@@ -603,7 +603,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) { if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
u16 info = CAPIMSG_U16(skb->data, 12); // Info field u16 info = CAPIMSG_U16(skb->data, 12); // Info field
if (info == 0) { if ((info & 0xff00) == 0) {
mutex_lock(&cdev->ncci_list_mtx); mutex_lock(&cdev->ncci_list_mtx);
capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
mutex_unlock(&cdev->ncci_list_mtx); mutex_unlock(&cdev->ncci_list_mtx);
......
...@@ -40,7 +40,7 @@ static int debugmode = 0; ...@@ -40,7 +40,7 @@ static int debugmode = 0;
MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux"); MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
MODULE_AUTHOR("Carsten Paeth"); MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_param(debugmode, uint, 0); module_param(debugmode, uint, S_IRUGO|S_IWUSR);
/* -------- type definitions ----------------------------------------- */ /* -------- type definitions ----------------------------------------- */
...@@ -671,8 +671,8 @@ static void n0(capidrv_contr * card, capidrv_ncci * ncci) ...@@ -671,8 +671,8 @@ static void n0(capidrv_contr * card, capidrv_ncci * ncci)
NULL, /* Useruserdata */ /* $$$$ */ NULL, /* Useruserdata */ /* $$$$ */
NULL /* Facilitydataarray */ NULL /* Facilitydataarray */
); );
send_message(card, &cmsg);
plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ); plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
send_message(card, &cmsg);
cmd.command = ISDN_STAT_BHUP; cmd.command = ISDN_STAT_BHUP;
cmd.driver = card->myid; cmd.driver = card->myid;
...@@ -924,8 +924,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg) ...@@ -924,8 +924,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
*/ */
capi_cmsg_answer(cmsg); capi_cmsg_answer(cmsg);
cmsg->Reject = 1; /* ignore */ cmsg->Reject = 1; /* ignore */
send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
send_message(card, cmsg);
printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n", printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
card->contrnr, card->contrnr,
cmd.parm.setup.phone, cmd.parm.setup.phone,
...@@ -974,8 +974,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg) ...@@ -974,8 +974,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
case 2: /* Call will be rejected. */ case 2: /* Call will be rejected. */
capi_cmsg_answer(cmsg); capi_cmsg_answer(cmsg);
cmsg->Reject = 2; /* reject call, normal call clearing */ cmsg->Reject = 2; /* reject call, normal call clearing */
send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
send_message(card, cmsg);
break; break;
default: default:
...@@ -983,8 +983,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg) ...@@ -983,8 +983,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
capi_cmsg_answer(cmsg); capi_cmsg_answer(cmsg);
cmsg->Reject = 8; /* reject call, cmsg->Reject = 8; /* reject call,
destination out of order */ destination out of order */
send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
send_message(card, cmsg);
break; break;
} }
return; return;
...@@ -1020,8 +1020,8 @@ static void handle_plci(_cmsg * cmsg) ...@@ -1020,8 +1020,8 @@ static void handle_plci(_cmsg * cmsg)
card->bchans[plcip->chan].disconnecting = 1; card->bchans[plcip->chan].disconnecting = 1;
plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND); plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
capi_cmsg_answer(cmsg); capi_cmsg_answer(cmsg);
send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP); plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
send_message(card, cmsg);
break; break;
case CAPI_DISCONNECT_CONF: /* plci */ case CAPI_DISCONNECT_CONF: /* plci */
...@@ -1078,8 +1078,8 @@ static void handle_plci(_cmsg * cmsg) ...@@ -1078,8 +1078,8 @@ static void handle_plci(_cmsg * cmsg)
if (card->bchans[plcip->chan].incoming) { if (card->bchans[plcip->chan].incoming) {
capi_cmsg_answer(cmsg); capi_cmsg_answer(cmsg);
send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND); plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
send_message(card, cmsg);
} else { } else {
capidrv_ncci *nccip; capidrv_ncci *nccip;
capi_cmsg_answer(cmsg); capi_cmsg_answer(cmsg);
...@@ -1098,13 +1098,14 @@ static void handle_plci(_cmsg * cmsg) ...@@ -1098,13 +1098,14 @@ static void handle_plci(_cmsg * cmsg)
NULL /* NCPI */ NULL /* NCPI */
); );
nccip->msgid = cmsg->Messagenumber; nccip->msgid = cmsg->Messagenumber;
plci_change_state(card, plcip,
EV_PLCI_CONNECT_ACTIVE_IND);
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
send_message(card, cmsg); send_message(card, cmsg);
cmd.command = ISDN_STAT_DCONN; cmd.command = ISDN_STAT_DCONN;
cmd.driver = card->myid; cmd.driver = card->myid;
cmd.arg = plcip->chan; cmd.arg = plcip->chan;
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
} }
break; break;
...@@ -1193,8 +1194,8 @@ static void handle_ncci(_cmsg * cmsg) ...@@ -1193,8 +1194,8 @@ static void handle_ncci(_cmsg * cmsg)
goto notfound; goto notfound;
capi_cmsg_answer(cmsg); capi_cmsg_answer(cmsg);
send_message(card, cmsg);
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND); ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
send_message(card, cmsg);
cmd.command = ISDN_STAT_BCONN; cmd.command = ISDN_STAT_BCONN;
cmd.driver = card->myid; cmd.driver = card->myid;
...@@ -1222,8 +1223,8 @@ static void handle_ncci(_cmsg * cmsg) ...@@ -1222,8 +1223,8 @@ static void handle_ncci(_cmsg * cmsg)
0, /* Reject */ 0, /* Reject */
NULL /* NCPI */ NULL /* NCPI */
); );
send_message(card, cmsg);
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP); ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
send_message(card, cmsg);
break; break;
} }
printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr); printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
...@@ -1299,8 +1300,8 @@ static void handle_ncci(_cmsg * cmsg) ...@@ -1299,8 +1300,8 @@ static void handle_ncci(_cmsg * cmsg)
card->bchans[nccip->chan].disconnecting = 1; card->bchans[nccip->chan].disconnecting = 1;
ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND); ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
capi_cmsg_answer(cmsg); capi_cmsg_answer(cmsg);
send_message(card, cmsg);
ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP); ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
send_message(card, cmsg);
break; break;
case CAPI_DISCONNECT_B3_CONF: /* ncci */ case CAPI_DISCONNECT_B3_CONF: /* ncci */
...@@ -2014,8 +2015,8 @@ static void send_listen(capidrv_contr *card) ...@@ -2014,8 +2015,8 @@ static void send_listen(capidrv_contr *card)
card->cipmask, card->cipmask,
card->cipmask2, card->cipmask2,
NULL, NULL); NULL, NULL);
send_message(card, &cmdcmsg);
listen_change_state(card, EV_LISTEN_REQ); listen_change_state(card, EV_LISTEN_REQ);
send_message(card, &cmdcmsg);
} }
static void listentimerfunc(unsigned long x) static void listentimerfunc(unsigned long x)
......
...@@ -334,7 +334,14 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, ...@@ -334,7 +334,14 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
return startbytes - numbytes; return startbytes - numbytes;
} }
/* process a block of data received from the device /**
* gigaset_m10x_input() - process a block of data received from the device
* @inbuf: received data and device descriptor structure.
*
* Called by hardware module {ser,usb}_gigaset with a block of received
* bytes. Separates the bytes received over the serial data channel into
* user data and command replies (locked/unlocked) according to the
* current state of the interface.
*/ */
void gigaset_m10x_input(struct inbuf_t *inbuf) void gigaset_m10x_input(struct inbuf_t *inbuf)
{ {
...@@ -543,16 +550,17 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) ...@@ -543,16 +550,17 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
return iraw_skb; return iraw_skb;
} }
/* gigaset_send_skb /**
* called by common.c to queue an skb for sending * gigaset_m10x_send_skb() - queue an skb for sending
* and start transmission if necessary * @bcs: B channel descriptor structure.
* parameters: * @skb: data to send.
* B Channel control structure *
* skb * Called by i4l.c to encode and queue an skb for sending, and start
* transmission if necessary.
*
* Return value: * Return value:
* number of bytes accepted for sending * number of bytes accepted for sending (skb->len) if ok,
* (skb->len if ok, 0 if out of buffer space) * error code < 0 (eg. -ENOMEM) on error
* or error code (< 0, eg. -EINVAL)
*/ */
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
{ {
......
...@@ -134,6 +134,7 @@ struct bas_cardstate { ...@@ -134,6 +134,7 @@ struct bas_cardstate {
#define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */
#define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */
#define BS_SUSPEND 0x100 /* USB port suspended */ #define BS_SUSPEND 0x100 /* USB port suspended */
#define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */
static struct gigaset_driver *driver = NULL; static struct gigaset_driver *driver = NULL;
...@@ -319,6 +320,21 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) ...@@ -319,6 +320,21 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
return -EINVAL; return -EINVAL;
} }
/* set/clear bits in base connection state, return previous state
*/
static inline int update_basstate(struct bas_cardstate *ucs,
int set, int clear)
{
unsigned long flags;
int state;
spin_lock_irqsave(&ucs->lock, flags);
state = ucs->basstate;
ucs->basstate = (state & ~clear) | set;
spin_unlock_irqrestore(&ucs->lock, flags);
return state;
}
/* error_hangup /* error_hangup
* hang up any existing connection because of an unrecoverable error * hang up any existing connection because of an unrecoverable error
* This function may be called from any context and takes care of scheduling * This function may be called from any context and takes care of scheduling
...@@ -350,12 +366,9 @@ static inline void error_hangup(struct bc_state *bcs) ...@@ -350,12 +366,9 @@ static inline void error_hangup(struct bc_state *bcs)
*/ */
static inline void error_reset(struct cardstate *cs) static inline void error_reset(struct cardstate *cs)
{ {
/* close AT command channel to recover (ignore errors) */ /* reset interrupt pipe to recover (ignore errors) */
req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); update_basstate(cs->hw.bas, BS_RESETTING, 0);
req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT);
//FIXME try to recover without bothering the user
dev_err(cs->dev,
"unrecoverable error - please disconnect Gigaset base to reset\n");
} }
/* check_pending /* check_pending
...@@ -398,8 +411,13 @@ static void check_pending(struct bas_cardstate *ucs) ...@@ -398,8 +411,13 @@ static void check_pending(struct bas_cardstate *ucs)
case HD_DEVICE_INIT_ACK: /* no reply expected */ case HD_DEVICE_INIT_ACK: /* no reply expected */
ucs->pending = 0; ucs->pending = 0;
break; break;
/* HD_READ_ATMESSAGE, HD_WRITE_ATMESSAGE, HD_RESET_INTERRUPTPIPE case HD_RESET_INTERRUPT_PIPE:
* are handled separately and should never end up here if (!(ucs->basstate & BS_RESETTING))
ucs->pending = 0;
break;
/*
* HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately
* and should never end up here
*/ */
default: default:
dev_warn(&ucs->interface->dev, dev_warn(&ucs->interface->dev,
...@@ -449,21 +467,6 @@ static void cmd_in_timeout(unsigned long data) ...@@ -449,21 +467,6 @@ static void cmd_in_timeout(unsigned long data)
error_reset(cs); error_reset(cs);
} }
/* 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;
spin_lock_irqsave(&ucs->lock, flags);
state = ucs->basstate;
ucs->basstate = (state & ~clear) | set;
spin_unlock_irqrestore(&ucs->lock, flags);
return state;
}
/* read_ctrl_callback /* read_ctrl_callback
* USB completion handler for control pipe input * USB completion handler for control pipe input
* called by the USB subsystem in interrupt context * called by the USB subsystem in interrupt context
...@@ -762,7 +765,8 @@ static void read_int_callback(struct urb *urb) ...@@ -762,7 +765,8 @@ static void read_int_callback(struct urb *urb)
break; break;
case HD_RESET_INTERRUPT_PIPE_ACK: case HD_RESET_INTERRUPT_PIPE_ACK:
gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK"); update_basstate(ucs, 0, BS_RESETTING);
dev_notice(cs->dev, "interrupt pipe reset\n");
break; break;
case HD_SUSPEND_END: case HD_SUSPEND_END:
...@@ -1331,28 +1335,24 @@ static void read_iso_tasklet(unsigned long data) ...@@ -1331,28 +1335,24 @@ static void read_iso_tasklet(unsigned long data)
rcvbuf = urb->transfer_buffer; rcvbuf = urb->transfer_buffer;
totleft = urb->actual_length; totleft = urb->actual_length;
for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) { for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) {
if (unlikely(urb->iso_frame_desc[frame].status)) { numbytes = urb->iso_frame_desc[frame].actual_length;
if (unlikely(urb->iso_frame_desc[frame].status))
dev_warn(cs->dev, dev_warn(cs->dev,
"isochronous read: frame %d: %s\n", "isochronous read: frame %d[%d]: %s\n",
frame, frame, numbytes,
get_usb_statmsg( get_usb_statmsg(
urb->iso_frame_desc[frame].status)); urb->iso_frame_desc[frame].status));
break; if (unlikely(numbytes > BAS_MAXFRAME))
}
numbytes = urb->iso_frame_desc[frame].actual_length;
if (unlikely(numbytes > BAS_MAXFRAME)) {
dev_warn(cs->dev, dev_warn(cs->dev,
"isochronous read: frame %d: " "isochronous read: frame %d: "
"numbytes (%d) > BAS_MAXFRAME\n", "numbytes (%d) > BAS_MAXFRAME\n",
frame, numbytes); frame, numbytes);
break;
}
if (unlikely(numbytes > totleft)) { if (unlikely(numbytes > totleft)) {
dev_warn(cs->dev,