2012-09-12 08:15:44

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: [PATCH 1/3] NFC: Handle RSET in SHDLC_CONNECTING state

As queue_work() does not guarantee ordered execution of sm_work it
can happen in crossover RSET usecase that connect timer will constantly
change the shdlc state from NEGOTIATING to CONNECTING before shdlc have
chance to handle incoming frame.

As a result the incoming RSET frame will remain not handled before putting
shdlc into DISCONNECTED state which is too late.

Signed-off-by: Waldemar Rymarkiewicz <[email protected]>
---
net/nfc/hci/shdlc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c
index fd75cec..fe66cbc 100644
--- a/net/nfc/hci/shdlc.c
+++ b/net/nfc/hci/shdlc.c
@@ -365,7 +365,8 @@ static void nfc_shdlc_rcv_u_frame(struct nfc_shdlc *shdlc,

switch (u_frame_modifier) {
case U_FRAME_RSET:
- if (shdlc->state == SHDLC_NEGOCIATING) {
+ if ( (shdlc->state == SHDLC_NEGOCIATING) ||
+ (shdlc->state == SHDLC_CONNECTING) ) {
/* we sent RSET, but chip wants to negociate */
if (skb->len > 0)
w = skb->data[0];
--
1.7.10



2012-09-12 08:15:56

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: [PATCH 3/3] NFC: Clean rcv_q to avoid handling of remaing RSET

During processing incoming RSET frame chip, possibly due to its internal
timout, could retrnasmit an another RSET which is next queued for processing
in shdlc layer.

To avoid processing of those remaining in rcv_q purge the queue. Otherwise it
will be handled in CONNECTED state which will result in disconnection.

Signed-off-by: Waldemar Rymarkiewicz <[email protected]>
---
net/nfc/hci/shdlc.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c
index 12feb58..6ede86c 100644
--- a/net/nfc/hci/shdlc.c
+++ b/net/nfc/hci/shdlc.c
@@ -381,6 +381,12 @@ static void nfc_shdlc_rcv_u_frame(struct nfc_shdlc *shdlc,
shdlc->srej_support = srej_support;
r = nfc_shdlc_connect_send_ua(shdlc);
nfc_shdlc_connect_complete(shdlc, r);
+
+ if (shdlc->rcv_q.qlen)
+ /* Handling incoming RSET the chip could issue an another one,
+ * possibly due to its internal timeout, so we have to make
+ * sure we won't handle these remaining on the rcv_q */
+ skb_queue_purge(&shdlc->rcv_q);
}
} else if (shdlc->state == SHDLC_CONNECTED) {
/*
--
1.7.10


2012-09-12 08:15:51

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: [PATCH 2/3] NFC: Fix ret check in nfc_shdlc_connect_complete

Typically, the r argument passed to nfc_shdlc_connect_complete()
comes from xmit() cb which returns, in successfull usecase, number
of successfully transmited bytes. Therefore, e.g. sending UA frame
the shdlc will go into wrong state (DISCONNECTED insted of CONNECTED).

Signed-off-by: Waldemar Rymarkiewicz <[email protected]>
---
net/nfc/hci/shdlc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c
index fe66cbc..12feb58 100644
--- a/net/nfc/hci/shdlc.c
+++ b/net/nfc/hci/shdlc.c
@@ -309,7 +309,7 @@ static void nfc_shdlc_connect_complete(struct nfc_shdlc *shdlc, int r)

del_timer_sync(&shdlc->connect_timer);

- if (r == 0) {
+ if (r >= 0) {
shdlc->ns = 0;
shdlc->nr = 0;
shdlc->dnr = 0;
--
1.7.10