summaryrefslogtreecommitdiff
path: root/drivers/ptp/ptp_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ptp/ptp_clock.c')
-rw-r--r--drivers/ptp/ptp_clock.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 1d920f8e20a8..ef020599b771 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -498,9 +498,21 @@ int ptp_clock_unregister(struct ptp_clock *ptp)
device_for_each_child(&ptp->dev, NULL, unregister_vclock);
}
+ /* Get the device to stop posix_clock_unregister() doing the last put
+ * and freeing the structure(s)
+ */
+ get_device(&ptp->dev);
+
+ /* Wake up any userspace waiting for an event. */
ptp->defunct = 1;
wake_up_interruptible(&ptp->tsev_wq);
+ /* Tear down the POSIX clock, which removes the user interface. */
+ posix_clock_unregister(&ptp->clock);
+
+ /* Disable all sources of event generation. */
+ ptp_disable_all_events(ptp);
+
if (ptp->kworker) {
kthread_cancel_delayed_work_sync(&ptp->aux_work);
kthread_destroy_worker(ptp->kworker);
@@ -510,7 +522,8 @@ int ptp_clock_unregister(struct ptp_clock *ptp)
if (ptp->pps_source)
pps_unregister_source(ptp->pps_source);
- posix_clock_unregister(&ptp->clock);
+ /* The final put, normally here, will invoke ptp_clock_release(). */
+ put_device(&ptp->dev);
return 0;
}