aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Rusalin <arusalin@dev.rtsoft.ru>2016-12-28 12:10:59 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2017-04-01 19:06:23 -0400
commit32ecc75ded72e0425713a7ffe2050fef6e54e564 (patch)
tree1aeff43036098aa123db09c34fa87b18f0087b14
parent5dd9c1bd61a7b684e54897a3a2546124c4077eda (diff)
NFC: pn533: change order operations in dev registation
Sometimes during probing and registration of pn533_i2c NULL pointer dereference happens. Reproduced in cycle of inserting and removing pn533_i2c and pn533 modules. Backtrace: [<8004205c>] (__queue_work) from [<80042324>] (queue_work_on+0x50/0x5c) r10:acdc7c80 r9:8006b330 r8:ac0dfb40 r7:ac50c600 r6:00000004 r5:acbbee40 r4:600f0113 [<800422d4>] (queue_work_on) from [<7f7d5b6c>] (pn533_recv_frame+0x158/0x1fc [pn533]) r7:ffffff87 r6:00000000 r5:acbbee40 r4:acbbee00 [<7f7d5a14>] (pn533_recv_frame [pn533]) from [<7f7df4b8>] (pn533_i2c_irq_thread_fn+0x184/0x) r6:acb2a000 r5:00000000 r4:acdc7b90 [<7f7df334>] (pn533_i2c_irq_thread_fn [pn533_i2c]) from [<8006b354>] (irq_thread_fn+0x24/0x) r7:00000000 r6:accde000 r5:ac0dfb40 r4:acdc7c80 ... Seems there is some race condition due registration of irq handler until all data stuctures that could be needed are ready. So I re-ordered some ops. After this, problem has gone. Changes in USB part was not tested, but it should not break anything. Signed-off-by: Andrey Rusalin <arusalin@dev.rtsoft.ru> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/nfc/pn533/i2c.c28
-rw-r--r--drivers/nfc/pn533/pn533.c42
-rw-r--r--drivers/nfc/pn533/pn533.h1
-rw-r--r--drivers/nfc/pn533/usb.c4
4 files changed, 48 insertions, 27 deletions
diff --git a/drivers/nfc/pn533/i2c.c b/drivers/nfc/pn533/i2c.c
index 11d78b43cf76..2c2fb9cfe10a 100644
--- a/drivers/nfc/pn533/i2c.c
+++ b/drivers/nfc/pn533/i2c.c
@@ -206,14 +206,6 @@ static int pn533_i2c_probe(struct i2c_client *client,
206 phy->i2c_dev = client; 206 phy->i2c_dev = client;
207 i2c_set_clientdata(client, phy); 207 i2c_set_clientdata(client, phy);
208 208
209 r = request_threaded_irq(client->irq, NULL, pn533_i2c_irq_thread_fn,
210 IRQF_TRIGGER_FALLING |
211 IRQF_SHARED | IRQF_ONESHOT,
212 PN533_I2C_DRIVER_NAME, phy);
213
214 if (r < 0)
215 nfc_err(&client->dev, "Unable to register IRQ handler\n");
216
217 priv = pn533_register_device(PN533_DEVICE_PN532, 209 priv = pn533_register_device(PN533_DEVICE_PN532,
218 PN533_NO_TYPE_B_PROTOCOLS, 210 PN533_NO_TYPE_B_PROTOCOLS,
219 PN533_PROTO_REQ_ACK_RESP, 211 PN533_PROTO_REQ_ACK_RESP,
@@ -223,16 +215,32 @@ static int pn533_i2c_probe(struct i2c_client *client,
223 215
224 if (IS_ERR(priv)) { 216 if (IS_ERR(priv)) {
225 r = PTR_ERR(priv); 217 r = PTR_ERR(priv);
226 goto err_register; 218 return r;
227 } 219 }
228 220
229 phy->priv = priv; 221 phy->priv = priv;
230 222
223 r = request_threaded_irq(client->irq, NULL, pn533_i2c_irq_thread_fn,
224 IRQF_TRIGGER_FALLING |
225 IRQF_SHARED | IRQF_ONESHOT,
226 PN533_I2C_DRIVER_NAME, phy);
227 if (r < 0) {
228 nfc_err(&client->dev, "Unable to register IRQ handler\n");
229 goto irq_rqst_err;
230 }
231
232 r = pn533_finalize_setup(priv);
233 if (r)
234 goto fn_setup_err;
235
231 return 0; 236 return 0;
232 237
233err_register: 238fn_setup_err:
234 free_irq(client->irq, phy); 239 free_irq(client->irq, phy);
235 240
241irq_rqst_err:
242 pn533_unregister_device(phy->priv);
243
236 return r; 244 return r;
237} 245}
238 246
diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c
index 712aa67e1770..65bbaa5fcdda 100644
--- a/drivers/nfc/pn533/pn533.c
+++ b/drivers/nfc/pn533/pn533.c
@@ -2570,6 +2570,31 @@ static int pn533_setup(struct pn533 *dev)
2570 return 0; 2570 return 0;
2571} 2571}
2572 2572
2573int pn533_finalize_setup(struct pn533 *dev)
2574{
2575
2576 struct pn533_fw_version fw_ver;
2577 int rc;
2578
2579 memset(&fw_ver, 0, sizeof(fw_ver));
2580
2581 rc = pn533_get_firmware_version(dev, &fw_ver);
2582 if (rc) {
2583 nfc_err(dev->dev, "Unable to get FW version\n");
2584 return rc;
2585 }
2586
2587 nfc_info(dev->dev, "NXP PN5%02X firmware ver %d.%d now attached\n",
2588 fw_ver.ic, fw_ver.ver, fw_ver.rev);
2589
2590 rc = pn533_setup(dev);
2591 if (rc)
2592 return rc;
2593
2594 return 0;
2595}
2596EXPORT_SYMBOL_GPL(pn533_finalize_setup);
2597
2573struct pn533 *pn533_register_device(u32 device_type, 2598struct pn533 *pn533_register_device(u32 device_type,
2574 u32 protocols, 2599 u32 protocols,
2575 enum pn533_protocol_type protocol_type, 2600 enum pn533_protocol_type protocol_type,
@@ -2579,7 +2604,6 @@ struct pn533 *pn533_register_device(u32 device_type,
2579 struct device *dev, 2604 struct device *dev,
2580 struct device *parent) 2605 struct device *parent)
2581{ 2606{
2582 struct pn533_fw_version fw_ver;
2583 struct pn533 *priv; 2607 struct pn533 *priv;
2584 int rc = -ENOMEM; 2608 int rc = -ENOMEM;
2585 2609
@@ -2622,15 +2646,6 @@ struct pn533 *pn533_register_device(u32 device_type,
2622 2646
2623 INIT_LIST_HEAD(&priv->cmd_queue); 2647 INIT_LIST_HEAD(&priv->cmd_queue);
2624 2648
2625 memset(&fw_ver, 0, sizeof(fw_ver));
2626 rc = pn533_get_firmware_version(priv, &fw_ver);
2627 if (rc < 0)
2628 goto destroy_wq;
2629
2630 nfc_info(dev, "NXP PN5%02X firmware ver %d.%d now attached\n",
2631 fw_ver.ic, fw_ver.ver, fw_ver.rev);
2632
2633
2634 priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, 2649 priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
2635 priv->ops->tx_header_len + 2650 priv->ops->tx_header_len +
2636 PN533_CMD_DATAEXCH_HEAD_LEN, 2651 PN533_CMD_DATAEXCH_HEAD_LEN,
@@ -2647,15 +2662,8 @@ struct pn533 *pn533_register_device(u32 device_type,
2647 if (rc) 2662 if (rc)
2648 goto free_nfc_dev; 2663 goto free_nfc_dev;
2649 2664
2650 rc = pn533_setup(priv);
2651 if (rc)
2652 goto unregister_nfc_dev;
2653
2654 return priv; 2665 return priv;
2655 2666
2656unregister_nfc_dev:
2657 nfc_unregister_device(priv->nfc_dev);
2658
2659free_nfc_dev: 2667free_nfc_dev:
2660 nfc_free_device(priv->nfc_dev); 2668 nfc_free_device(priv->nfc_dev);
2661 2669
diff --git a/drivers/nfc/pn533/pn533.h b/drivers/nfc/pn533/pn533.h
index 553c7d171fd1..88d569666c51 100644
--- a/drivers/nfc/pn533/pn533.h
+++ b/drivers/nfc/pn533/pn533.h
@@ -231,6 +231,7 @@ struct pn533 *pn533_register_device(u32 device_type,
231 struct device *dev, 231 struct device *dev,
232 struct device *parent); 232 struct device *parent);
233 233
234int pn533_finalize_setup(struct pn533 *dev);
234void pn533_unregister_device(struct pn533 *priv); 235void pn533_unregister_device(struct pn533 *priv);
235void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status); 236void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status);
236 237
diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c
index 33ed78be2750..000159ea9c5f 100644
--- a/drivers/nfc/pn533/usb.c
+++ b/drivers/nfc/pn533/usb.c
@@ -543,6 +543,10 @@ static int pn533_usb_probe(struct usb_interface *interface,
543 543
544 phy->priv = priv; 544 phy->priv = priv;
545 545
546 rc = pn533_finalize_setup(priv);
547 if (rc)
548 goto error;
549
546 usb_set_intfdata(interface, phy); 550 usb_set_intfdata(interface, phy);
547 551
548 return 0; 552 return 0;