From 7854a44526de84142e367f08288c9f3a33c4c8ee Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Tue, 7 Jun 2016 16:21:52 +0200 Subject: NFC: digital: Add a delay between poll cycles This replaces the polling work struct with a delayed work struct and add a 10 ms delay between 2 poll cycles. This avoids to flood the device with 'switch off'/'switch on' commands. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/digital_core.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'net/nfc/digital_core.c') diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index dd9003f38822..27769ac89d27 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -30,6 +30,9 @@ #define DIGITAL_PROTO_ISO15693_RF_TECH NFC_PROTO_ISO15693_MASK +/* Delay between each poll frame (ms) */ +#define DIGITAL_POLL_INTERVAL 10 + struct digital_cmd { struct list_head queue; @@ -419,7 +422,8 @@ void digital_poll_next_tech(struct nfc_digital_dev *ddev) mutex_unlock(&ddev->poll_lock); - schedule_work(&ddev->poll_work); + schedule_delayed_work(&ddev->poll_work, + msecs_to_jiffies(DIGITAL_POLL_INTERVAL)); } static void digital_wq_poll(struct work_struct *work) @@ -428,7 +432,7 @@ static void digital_wq_poll(struct work_struct *work) struct digital_poll_tech *poll_tech; struct nfc_digital_dev *ddev = container_of(work, struct nfc_digital_dev, - poll_work); + poll_work.work); mutex_lock(&ddev->poll_lock); if (!ddev->poll_tech_count) { @@ -543,7 +547,7 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, return -EINVAL; } - schedule_work(&ddev->poll_work); + schedule_delayed_work(&ddev->poll_work, 0); return 0; } @@ -564,7 +568,7 @@ static void digital_stop_poll(struct nfc_dev *nfc_dev) mutex_unlock(&ddev->poll_lock); - cancel_work_sync(&ddev->poll_work); + cancel_delayed_work_sync(&ddev->poll_work); digital_abort_cmd(ddev); } @@ -770,7 +774,7 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, INIT_WORK(&ddev->cmd_complete_work, digital_wq_cmd_complete); mutex_init(&ddev->poll_lock); - INIT_WORK(&ddev->poll_work, digital_wq_poll); + INIT_DELAYED_WORK(&ddev->poll_work, digital_wq_poll); if (supported_protocols & NFC_PROTO_JEWEL_MASK) ddev->protocols |= NFC_PROTO_JEWEL_MASK; @@ -832,7 +836,7 @@ void nfc_digital_unregister_device(struct nfc_digital_dev *ddev) ddev->poll_tech_count = 0; mutex_unlock(&ddev->poll_lock); - cancel_work_sync(&ddev->poll_work); + cancel_delayed_work_sync(&ddev->poll_work); cancel_work_sync(&ddev->cmd_work); cancel_work_sync(&ddev->cmd_complete_work); -- cgit v1.2.3-59-g8ed1b From 82e57952869fbbdf09d8f9e7ac284df13741e93d Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Thu, 16 Jun 2016 20:24:43 +0200 Subject: NFC: digital: Call pending command callbacks at device unregister With this patch, when freeing the command queue in the module unregister function, the callbacks of the commands still queued are called with a ENODEV error. This gives a chance to the command issuer to free any memory it could have allocate. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/digital_core.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'net/nfc/digital_core.c') diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 27769ac89d27..6e0b255aec66 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -842,6 +842,14 @@ void nfc_digital_unregister_device(struct nfc_digital_dev *ddev) list_for_each_entry_safe(cmd, n, &ddev->cmd_queue, queue) { list_del(&cmd->queue); + + /* Call the command callback if any and pass it a ENODEV error. + * This gives a chance to the command issuer to free any + * allocated buffer. + */ + if (cmd->cmd_cb) + cmd->cmd_cb(ddev, cmd->cb_context, ERR_PTR(-ENODEV)); + kfree(cmd->mdaa_params); kfree(cmd); } -- cgit v1.2.3-59-g8ed1b From af66df0f53b9120437556d8eb00d70a36e791258 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Thu, 16 Jun 2016 20:24:44 +0200 Subject: NFC: digital: Set the command pending flag There is a flag in the command structure indicating that this command is pending. It was checked before sending the command to not send the same command twice but it was actually never set. This is now fixed. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/digital_core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net/nfc/digital_core.c') diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 6e0b255aec66..0146e42ee28f 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -176,6 +176,8 @@ static void digital_wq_cmd(struct work_struct *work) return; } + cmd->pending = 1; + mutex_unlock(&ddev->cmd_lock); if (cmd->req) -- cgit v1.2.3-59-g8ed1b From 3cc952dbf1a7176b9247da4cd2612c9ddc1d1b51 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Thu, 16 Jun 2016 20:24:45 +0200 Subject: NFC: digital: Abort last command when dep link goes down With this patch, the Digital Protocol layer abort the last issued command when the dep link goes down. That way it does not have to wait for the driver to reply with a timeout error before sending a new command (i.e. a start poll command if constant polling is on). Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/digital_core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net/nfc/digital_core.c') diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 0146e42ee28f..0fd5518bf252 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -612,6 +612,8 @@ static int digital_dep_link_down(struct nfc_dev *nfc_dev) { struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); + digital_abort_cmd(ddev); + ddev->curr_protocol = 0; return 0; -- cgit v1.2.3-59-g8ed1b