NFC: Convert pn533 from tasklet to workqueues
There is no need for soft IRQ contexts, and workqueues are more flexible. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
ffc29315e5
commit
4849f85ee3
@@ -266,9 +266,10 @@ struct pn533 {
|
|||||||
int in_maxlen;
|
int in_maxlen;
|
||||||
struct pn533_frame *in_frame;
|
struct pn533_frame *in_frame;
|
||||||
|
|
||||||
struct tasklet_struct tasklet;
|
struct workqueue_struct *wq;
|
||||||
struct pn533_frame *tklt_in_frame;
|
struct work_struct cmd_work;
|
||||||
int tklt_in_error;
|
struct pn533_frame *wq_in_frame;
|
||||||
|
int wq_in_error;
|
||||||
|
|
||||||
pn533_cmd_complete_t cmd_complete;
|
pn533_cmd_complete_t cmd_complete;
|
||||||
void *cmd_complete_arg;
|
void *cmd_complete_arg;
|
||||||
@@ -383,15 +384,21 @@ static bool pn533_rx_frame_is_cmd_response(struct pn533_frame *frame, u8 cmd)
|
|||||||
return (PN533_FRAME_CMD(frame) == PN533_CMD_RESPONSE(cmd));
|
return (PN533_FRAME_CMD(frame) == PN533_CMD_RESPONSE(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pn533_tasklet_cmd_complete(unsigned long arg)
|
|
||||||
|
static void pn533_wq_cmd_complete(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct pn533 *dev = (struct pn533 *) arg;
|
struct pn533 *dev = container_of(work, struct pn533, cmd_work);
|
||||||
struct pn533_frame *in_frame = dev->tklt_in_frame;
|
struct pn533_frame *in_frame;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (dev->tklt_in_error)
|
if (dev == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
in_frame = dev->wq_in_frame;
|
||||||
|
|
||||||
|
if (dev->wq_in_error)
|
||||||
rc = dev->cmd_complete(dev, dev->cmd_complete_arg, NULL,
|
rc = dev->cmd_complete(dev, dev->cmd_complete_arg, NULL,
|
||||||
dev->tklt_in_error);
|
dev->wq_in_error);
|
||||||
else
|
else
|
||||||
rc = dev->cmd_complete(dev, dev->cmd_complete_arg,
|
rc = dev->cmd_complete(dev, dev->cmd_complete_arg,
|
||||||
PN533_FRAME_CMD_PARAMS_PTR(in_frame),
|
PN533_FRAME_CMD_PARAMS_PTR(in_frame),
|
||||||
@@ -406,7 +413,7 @@ static void pn533_recv_response(struct urb *urb)
|
|||||||
struct pn533 *dev = urb->context;
|
struct pn533 *dev = urb->context;
|
||||||
struct pn533_frame *in_frame;
|
struct pn533_frame *in_frame;
|
||||||
|
|
||||||
dev->tklt_in_frame = NULL;
|
dev->wq_in_frame = NULL;
|
||||||
|
|
||||||
switch (urb->status) {
|
switch (urb->status) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -417,36 +424,36 @@ static void pn533_recv_response(struct urb *urb)
|
|||||||
case -ESHUTDOWN:
|
case -ESHUTDOWN:
|
||||||
nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
|
nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
|
||||||
" status: %d", urb->status);
|
" status: %d", urb->status);
|
||||||
dev->tklt_in_error = urb->status;
|
dev->wq_in_error = urb->status;
|
||||||
goto sched_tasklet;
|
goto sched_wq;
|
||||||
default:
|
default:
|
||||||
nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
|
nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
|
||||||
" %d", urb->status);
|
" %d", urb->status);
|
||||||
dev->tklt_in_error = urb->status;
|
dev->wq_in_error = urb->status;
|
||||||
goto sched_tasklet;
|
goto sched_wq;
|
||||||
}
|
}
|
||||||
|
|
||||||
in_frame = dev->in_urb->transfer_buffer;
|
in_frame = dev->in_urb->transfer_buffer;
|
||||||
|
|
||||||
if (!pn533_rx_frame_is_valid(in_frame)) {
|
if (!pn533_rx_frame_is_valid(in_frame)) {
|
||||||
nfc_dev_err(&dev->interface->dev, "Received an invalid frame");
|
nfc_dev_err(&dev->interface->dev, "Received an invalid frame");
|
||||||
dev->tklt_in_error = -EIO;
|
dev->wq_in_error = -EIO;
|
||||||
goto sched_tasklet;
|
goto sched_wq;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pn533_rx_frame_is_cmd_response(in_frame, dev->cmd)) {
|
if (!pn533_rx_frame_is_cmd_response(in_frame, dev->cmd)) {
|
||||||
nfc_dev_err(&dev->interface->dev, "The received frame is not "
|
nfc_dev_err(&dev->interface->dev, "The received frame is not "
|
||||||
"response to the last command");
|
"response to the last command");
|
||||||
dev->tklt_in_error = -EIO;
|
dev->wq_in_error = -EIO;
|
||||||
goto sched_tasklet;
|
goto sched_wq;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_dev_dbg(&dev->interface->dev, "Received a valid frame");
|
nfc_dev_dbg(&dev->interface->dev, "Received a valid frame");
|
||||||
dev->tklt_in_error = 0;
|
dev->wq_in_error = 0;
|
||||||
dev->tklt_in_frame = in_frame;
|
dev->wq_in_frame = in_frame;
|
||||||
|
|
||||||
sched_tasklet:
|
sched_wq:
|
||||||
tasklet_schedule(&dev->tasklet);
|
queue_work(dev->wq, &dev->cmd_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags)
|
static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags)
|
||||||
@@ -471,21 +478,21 @@ static void pn533_recv_ack(struct urb *urb)
|
|||||||
case -ESHUTDOWN:
|
case -ESHUTDOWN:
|
||||||
nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
|
nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
|
||||||
" status: %d", urb->status);
|
" status: %d", urb->status);
|
||||||
dev->tklt_in_error = urb->status;
|
dev->wq_in_error = urb->status;
|
||||||
goto sched_tasklet;
|
goto sched_wq;
|
||||||
default:
|
default:
|
||||||
nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
|
nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
|
||||||
" %d", urb->status);
|
" %d", urb->status);
|
||||||
dev->tklt_in_error = urb->status;
|
dev->wq_in_error = urb->status;
|
||||||
goto sched_tasklet;
|
goto sched_wq;
|
||||||
}
|
}
|
||||||
|
|
||||||
in_frame = dev->in_urb->transfer_buffer;
|
in_frame = dev->in_urb->transfer_buffer;
|
||||||
|
|
||||||
if (!pn533_rx_frame_is_ack(in_frame)) {
|
if (!pn533_rx_frame_is_ack(in_frame)) {
|
||||||
nfc_dev_err(&dev->interface->dev, "Received an invalid ack");
|
nfc_dev_err(&dev->interface->dev, "Received an invalid ack");
|
||||||
dev->tklt_in_error = -EIO;
|
dev->wq_in_error = -EIO;
|
||||||
goto sched_tasklet;
|
goto sched_wq;
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_dev_dbg(&dev->interface->dev, "Received a valid ack");
|
nfc_dev_dbg(&dev->interface->dev, "Received a valid ack");
|
||||||
@@ -494,15 +501,15 @@ static void pn533_recv_ack(struct urb *urb)
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
nfc_dev_err(&dev->interface->dev, "usb_submit_urb failed with"
|
nfc_dev_err(&dev->interface->dev, "usb_submit_urb failed with"
|
||||||
" result %d", rc);
|
" result %d", rc);
|
||||||
dev->tklt_in_error = rc;
|
dev->wq_in_error = rc;
|
||||||
goto sched_tasklet;
|
goto sched_wq;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sched_tasklet:
|
sched_wq:
|
||||||
dev->tklt_in_frame = NULL;
|
dev->wq_in_frame = NULL;
|
||||||
tasklet_schedule(&dev->tasklet);
|
queue_work(dev->wq, &dev->cmd_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags)
|
static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags)
|
||||||
@@ -1668,7 +1675,10 @@ static int pn533_probe(struct usb_interface *interface,
|
|||||||
NULL, 0,
|
NULL, 0,
|
||||||
pn533_send_complete, dev);
|
pn533_send_complete, dev);
|
||||||
|
|
||||||
tasklet_init(&dev->tasklet, pn533_tasklet_cmd_complete, (ulong)dev);
|
INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete);
|
||||||
|
dev->wq = create_singlethread_workqueue("pn533");
|
||||||
|
if (dev->wq == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
usb_set_intfdata(interface, dev);
|
usb_set_intfdata(interface, dev);
|
||||||
|
|
||||||
@@ -1678,7 +1688,7 @@ static int pn533_probe(struct usb_interface *interface,
|
|||||||
rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
|
rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
|
||||||
dev->in_maxlen);
|
dev->in_maxlen);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto kill_tasklet;
|
goto destroy_wq;
|
||||||
|
|
||||||
fw_ver = (struct pn533_fw_version *)
|
fw_ver = (struct pn533_fw_version *)
|
||||||
PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame);
|
PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame);
|
||||||
@@ -1694,7 +1704,7 @@ static int pn533_probe(struct usb_interface *interface,
|
|||||||
PN533_CMD_DATAEXCH_HEAD_LEN,
|
PN533_CMD_DATAEXCH_HEAD_LEN,
|
||||||
PN533_FRAME_TAIL_SIZE);
|
PN533_FRAME_TAIL_SIZE);
|
||||||
if (!dev->nfc_dev)
|
if (!dev->nfc_dev)
|
||||||
goto kill_tasklet;
|
goto destroy_wq;
|
||||||
|
|
||||||
nfc_set_parent_dev(dev->nfc_dev, &interface->dev);
|
nfc_set_parent_dev(dev->nfc_dev, &interface->dev);
|
||||||
nfc_set_drvdata(dev->nfc_dev, dev);
|
nfc_set_drvdata(dev->nfc_dev, dev);
|
||||||
@@ -1720,8 +1730,8 @@ static int pn533_probe(struct usb_interface *interface,
|
|||||||
|
|
||||||
free_nfc_dev:
|
free_nfc_dev:
|
||||||
nfc_free_device(dev->nfc_dev);
|
nfc_free_device(dev->nfc_dev);
|
||||||
kill_tasklet:
|
destroy_wq:
|
||||||
tasklet_kill(&dev->tasklet);
|
destroy_workqueue(dev->wq);
|
||||||
error:
|
error:
|
||||||
kfree(dev->in_frame);
|
kfree(dev->in_frame);
|
||||||
usb_free_urb(dev->in_urb);
|
usb_free_urb(dev->in_urb);
|
||||||
@@ -1744,7 +1754,7 @@ static void pn533_disconnect(struct usb_interface *interface)
|
|||||||
usb_kill_urb(dev->in_urb);
|
usb_kill_urb(dev->in_urb);
|
||||||
usb_kill_urb(dev->out_urb);
|
usb_kill_urb(dev->out_urb);
|
||||||
|
|
||||||
tasklet_kill(&dev->tasklet);
|
destroy_workqueue(dev->wq);
|
||||||
|
|
||||||
kfree(dev->in_frame);
|
kfree(dev->in_frame);
|
||||||
usb_free_urb(dev->in_urb);
|
usb_free_urb(dev->in_urb);
|
||||||
|
Reference in New Issue
Block a user