Commit 3f9c5669 authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by Linus Torvalds

IrDA trivial fixes:

o [CORRECT] Handle signals while IrSock is blocked on Tx
o [CORRECT] Fix race condition in LAP when receiving with pf bit
o [CRITICA] Prevent queuing Tx data before IrComm is ready
o [FEATURE] Warn user of common misuse of IrLPT
parent ee8bc02e
...@@ -44,6 +44,11 @@ ...@@ -44,6 +44,11 @@
#define IRCOMM_TTY_MAJOR 161 #define IRCOMM_TTY_MAJOR 161
#define IRCOMM_TTY_MINOR 0 #define IRCOMM_TTY_MINOR 0
/* This is used as an initial value to max_header_size before the proper
* value is filled in (5 for ttp, 4 for lmp). This allow us to detect
* the state of the underlying connection. - Jean II */
#define IRCOMM_TTY_HDR_UNITIALISED 32
/* /*
* IrCOMM TTY driver state * IrCOMM TTY driver state
*/ */
......
...@@ -1286,6 +1286,9 @@ static int irda_sendmsg(struct socket *sock, struct msghdr *msg, int len, ...@@ -1286,6 +1286,9 @@ static int irda_sendmsg(struct socket *sock, struct msghdr *msg, int len,
/* Check if we are still connected */ /* Check if we are still connected */
if (sk->state != TCP_ESTABLISHED) if (sk->state != TCP_ESTABLISHED)
return -ENOTCONN; return -ENOTCONN;
/* Handle signals */
if (signal_pending(current))
return -ERESTARTSYS;
} }
/* Check that we don't send out to big frames */ /* Check that we don't send out to big frames */
......
...@@ -416,7 +416,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -416,7 +416,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
self->line = line; self->line = line;
self->tqueue.routine = ircomm_tty_do_softint; self->tqueue.routine = ircomm_tty_do_softint;
self->tqueue.data = self; self->tqueue.data = self;
self->max_header_size = 5; self->max_header_size = IRCOMM_TTY_HDR_UNITIALISED;
self->max_data_size = 64-self->max_header_size; self->max_data_size = 64-self->max_header_size;
self->close_delay = 5*HZ/10; self->close_delay = 5*HZ/10;
self->closing_wait = 30*HZ; self->closing_wait = 30*HZ;
...@@ -695,6 +695,20 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, ...@@ -695,6 +695,20 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user,
ASSERT(self != NULL, return -1;); ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
/* We may receive packets from the TTY even before we have finished
* our setup. Not cool.
* The problem is that we would allocate a skb with bogus header and
* data size, and when adding data to it later we would get
* confused.
* Better to not accept data until we are properly setup. Use bogus
* header size to check that (safest way to detect it).
* Jean II */
if (self->max_header_size == IRCOMM_TTY_HDR_UNITIALISED) {
/* TTY will retry */
IRDA_DEBUG(2, __FUNCTION__ "() : not initialised\n");
return len;
}
save_flags(flags); save_flags(flags);
cli(); cli();
...@@ -791,8 +805,12 @@ static int ircomm_tty_write_room(struct tty_struct *tty) ...@@ -791,8 +805,12 @@ static int ircomm_tty_write_room(struct tty_struct *tty)
ASSERT(self != NULL, return -1;); ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
/* Check if we are allowed to transmit any data */ /* Check if we are allowed to transmit any data.
if (tty->hw_stopped) * hw_stopped is the regular flow control.
* max_header_size tells us if the channel is initialised or not.
* Jean II */
if ((tty->hw_stopped) ||
(self->max_header_size == IRCOMM_TTY_HDR_UNITIALISED))
ret = 0; ret = 0;
else { else {
save_flags(flags); save_flags(flags);
......
...@@ -93,6 +93,9 @@ void ircomm_tty_change_speed(struct ircomm_tty_cb *self) ...@@ -93,6 +93,9 @@ void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
if (cflag & CRTSCTS) { if (cflag & CRTSCTS) {
self->flags |= ASYNC_CTS_FLOW; self->flags |= ASYNC_CTS_FLOW;
self->settings.flow_control |= IRCOMM_RTS_CTS_IN; self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
/* This got me. Bummer. Jean II */
if (self->service_type == IRCOMM_3_WIRE_RAW)
WARNING(__FUNCTION__ "(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n");
} else { } else {
self->flags &= ~ASYNC_CTS_FLOW; self->flags &= ~ASYNC_CTS_FLOW;
self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN; self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
......
...@@ -174,6 +174,12 @@ static void irlap_poll_timer_expired(void *data) ...@@ -174,6 +174,12 @@ static void irlap_poll_timer_expired(void *data)
irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL); irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL);
} }
/*
* Calculate and set time before we will have to send back the pf bit
* to the peer. Use in primary.
* Make sure that state is XMIT_P/XMIT_S when calling this function
* (and that nobody messed up with the state). - Jean II
*/
void irlap_start_poll_timer(struct irlap_cb *self, int timeout) void irlap_start_poll_timer(struct irlap_cb *self, int timeout)
{ {
ASSERT(self != NULL, return;); ASSERT(self != NULL, return;);
...@@ -1163,15 +1169,26 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1163,15 +1169,26 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
self->ack_required = TRUE; self->ack_required = TRUE;
irlap_wait_min_turn_around(self, &self->qos_tx); irlap_wait_min_turn_around(self, &self->qos_tx);
/*
* Important to switch state before calling
* upper layers
*/
irlap_next_state(self, LAP_XMIT_P);
/* Call higher layer *before* changing state
* to give them a chance to send data in the
* next LAP frame.
* Jean II */
irlap_data_indication(self, skb, FALSE); irlap_data_indication(self, skb, FALSE);
/* This is the last frame */ /* XMIT states are the most dangerous state
* to be in, because user requests are
* processed directly and may change state.
* On the other hand, in NDM_P, those
* requests are queued and we will process
* them when we return to irlap_do_event().
* Jean II
*/
irlap_next_state(self, LAP_XMIT_P);
/* This is the last frame.
* Make sure it's always called in XMIT state.
* - Jean II */
irlap_start_poll_timer(self, self->poll_timeout); irlap_start_poll_timer(self, self->poll_timeout);
} }
break; break;
...@@ -1309,6 +1326,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1309,6 +1326,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
} else { } else {
del_timer(&self->final_timer); del_timer(&self->final_timer);
irlap_data_indication(self, skb, TRUE); irlap_data_indication(self, skb, TRUE);
irlap_next_state(self, LAP_XMIT_P);
printk(__FUNCTION__ "(): RECV_UI_FRAME: next state %s\n", irlap_state[self->state]); printk(__FUNCTION__ "(): RECV_UI_FRAME: next state %s\n", irlap_state[self->state]);
irlap_start_poll_timer(self, self->poll_timeout); irlap_start_poll_timer(self, self->poll_timeout);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment