summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Ricard <christophe.ricard@gmail.com>2014-04-24 21:19:34 (GMT)
committerSamuel Ortiz <sameo@linux.intel.com>2014-05-04 23:01:23 (GMT)
commita3c5d8fb7ffa8850f3d2fc01e1dde0709a3954f9 (patch)
treeb8cc659914079b6811af7c393ad6664359a0fd70
parentc97ffdbf51ec3f944e6661ecb16985d47c8073c7 (diff)
downloadlinux-a3c5d8fb7ffa8850f3d2fc01e1dde0709a3954f9.tar.xz
NFC: st21nfca: Synchronize i2c Tx and Rx path
Stabilize communication by using a mutex. This avoids running a write transaction during a read retry or a read transaction during a write retry. Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/nfc/st21nfca/i2c.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index 48f8e23..b64d8e2 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -89,6 +89,7 @@ struct st21nfca_i2c_phy {
* and prevents normal operation.
*/
int hard_fault;
+ struct mutex phy_lock;
};
static u8 len_seq[] = { 13, 24, 15, 29 };
static u16 wait_tab[] = { 2, 3, 5, 15, 20, 40};
@@ -245,11 +246,13 @@ static int st21nfca_hci_i2c_write(void *phy_id, struct sk_buff *skb)
* Manage sleep mode
* Try 3 times to send data with delay between each
*/
+ mutex_lock(&phy->phy_lock);
for (i = 0; i < ARRAY_SIZE(wait_tab) && r < 0; i++) {
r = i2c_master_send(client, tmp, j);
if (r < 0)
msleep(wait_tab[i]);
}
+ mutex_unlock(&phy->phy_lock);
if (r >= 0) {
if (r != j)
@@ -375,11 +378,13 @@ static int st21nfca_hci_i2c_read(struct st21nfca_i2c_phy *phy,
* RF or SWP interface
*/
r = 0;
+ mutex_lock(&phy->phy_lock);
for (i = 0; i < ARRAY_SIZE(wait_tab) && r <= 0; i++) {
r = i2c_master_recv(client, buf, len);
if (r < 0)
msleep(wait_tab[i]);
}
+ mutex_unlock(&phy->phy_lock);
if (r != len) {
phy->current_read_len = 0;
@@ -575,6 +580,7 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
phy->current_read_len = 0;
phy->crc_trials = 0;
+ mutex_init(&phy->phy_lock);
i2c_set_clientdata(client, phy);
pdata = client->dev.platform_data;