NFC: Don't handle consequent RSET frames after UA
During processing incoming RSET frame chip, possibly due to its internal timout, can retrnasmit an another RSET which is next queued for processing in shdlc layer. In case when we accept processed RSET skip those remaining on the rcv queue until chip will send it's first S or I frame. This will mean the chip completed connection as well. Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
9010e39f50
commit
12bfd1e890
1 changed files with 31 additions and 7 deletions
|
@ -32,7 +32,8 @@ enum shdlc_state {
|
|||
SHDLC_DISCONNECTED = 0,
|
||||
SHDLC_CONNECTING = 1,
|
||||
SHDLC_NEGOCIATING = 2,
|
||||
SHDLC_CONNECTED = 3
|
||||
SHDLC_HALF_CONNECTED = 3,
|
||||
SHDLC_CONNECTED = 4
|
||||
};
|
||||
|
||||
struct llc_shdlc {
|
||||
|
@ -363,7 +364,7 @@ static void llc_shdlc_connect_complete(struct llc_shdlc *shdlc, int r)
|
|||
shdlc->nr = 0;
|
||||
shdlc->dnr = 0;
|
||||
|
||||
shdlc->state = SHDLC_CONNECTED;
|
||||
shdlc->state = SHDLC_HALF_CONNECTED;
|
||||
} else {
|
||||
shdlc->state = SHDLC_DISCONNECTED;
|
||||
}
|
||||
|
@ -414,9 +415,13 @@ static void llc_shdlc_rcv_u_frame(struct llc_shdlc *shdlc,
|
|||
|
||||
switch (u_frame_modifier) {
|
||||
case U_FRAME_RSET:
|
||||
if ((shdlc->state == SHDLC_NEGOCIATING) ||
|
||||
(shdlc->state == SHDLC_CONNECTING)) {
|
||||
/* we sent RSET, but chip wants to negociate */
|
||||
switch (shdlc->state) {
|
||||
case SHDLC_NEGOCIATING:
|
||||
case SHDLC_CONNECTING:
|
||||
/*
|
||||
* We sent RSET, but chip wants to negociate or we
|
||||
* got RSET before we managed to send out our.
|
||||
*/
|
||||
if (skb->len > 0)
|
||||
w = skb->data[0];
|
||||
|
||||
|
@ -431,19 +436,31 @@ static void llc_shdlc_rcv_u_frame(struct llc_shdlc *shdlc,
|
|||
r = llc_shdlc_connect_send_ua(shdlc);
|
||||
llc_shdlc_connect_complete(shdlc, r);
|
||||
}
|
||||
} else if (shdlc->state == SHDLC_CONNECTED) {
|
||||
break;
|
||||
case SHDLC_HALF_CONNECTED:
|
||||
/*
|
||||
* Chip resent RSET due to its timeout - Ignote it
|
||||
* as we already sent UA.
|
||||
*/
|
||||
break;
|
||||
case SHDLC_CONNECTED:
|
||||
/*
|
||||
* Chip wants to reset link. This is unexpected and
|
||||
* unsupported.
|
||||
*/
|
||||
shdlc->hard_fault = -ECONNRESET;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case U_FRAME_UA:
|
||||
if ((shdlc->state == SHDLC_CONNECTING &&
|
||||
shdlc->connect_tries > 0) ||
|
||||
(shdlc->state == SHDLC_NEGOCIATING))
|
||||
(shdlc->state == SHDLC_NEGOCIATING)) {
|
||||
llc_shdlc_connect_complete(shdlc, 0);
|
||||
shdlc->state = SHDLC_CONNECTED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -470,11 +487,17 @@ static void llc_shdlc_handle_rcv_queue(struct llc_shdlc *shdlc)
|
|||
switch (control & SHDLC_CONTROL_HEAD_MASK) {
|
||||
case SHDLC_CONTROL_HEAD_I:
|
||||
case SHDLC_CONTROL_HEAD_I2:
|
||||
if (shdlc->state == SHDLC_HALF_CONNECTED)
|
||||
shdlc->state = SHDLC_CONNECTED;
|
||||
|
||||
ns = (control & SHDLC_CONTROL_NS_MASK) >> 3;
|
||||
nr = control & SHDLC_CONTROL_NR_MASK;
|
||||
llc_shdlc_rcv_i_frame(shdlc, skb, ns, nr);
|
||||
break;
|
||||
case SHDLC_CONTROL_HEAD_S:
|
||||
if (shdlc->state == SHDLC_HALF_CONNECTED)
|
||||
shdlc->state = SHDLC_CONNECTED;
|
||||
|
||||
s_frame_type = (control & SHDLC_CONTROL_TYPE_MASK) >> 3;
|
||||
nr = control & SHDLC_CONTROL_NR_MASK;
|
||||
llc_shdlc_rcv_s_frame(shdlc, s_frame_type, nr);
|
||||
|
@ -633,6 +656,7 @@ static void llc_shdlc_sm_work(struct work_struct *work)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case SHDLC_HALF_CONNECTED:
|
||||
case SHDLC_CONNECTED:
|
||||
llc_shdlc_handle_rcv_queue(shdlc);
|
||||
llc_shdlc_handle_send_queue(shdlc);
|
||||
|
|
Loading…
Reference in a new issue