diff options
Diffstat (limited to 'net/nfc/digital_core.c')
-rw-r--r-- | net/nfc/digital_core.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index dd9003f38822..0fd5518bf252 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; @@ -173,6 +176,8 @@ static void digital_wq_cmd(struct work_struct *work) return; } + cmd->pending = 1; + mutex_unlock(&ddev->cmd_lock); if (cmd->req) @@ -419,7 +424,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 +434,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 +549,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 +570,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); } @@ -606,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; @@ -770,7 +778,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,12 +840,20 @@ 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); 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); } |