]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/ptp/ptp_clock.c
ptp: fix the race between the release of ptp_clock and cdev
[mirror_ubuntu-bionic-kernel.git] / drivers / ptp / ptp_clock.c
index c64903a5978fb1a78ec214447d55819e3201a4bf..b818f65480c152bda2209fb4a76be083da719ccc 100644 (file)
@@ -175,9 +175,9 @@ static struct posix_clock_operations ptp_clock_ops = {
        .read           = ptp_read,
 };
 
-static void delete_ptp_clock(struct posix_clock *pc)
+static void ptp_clock_release(struct device *dev)
 {
-       struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
+       struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
 
        mutex_destroy(&ptp->tsevq_mux);
        mutex_destroy(&ptp->pincfg_mux);
@@ -222,7 +222,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
        }
 
        ptp->clock.ops = ptp_clock_ops;
-       ptp->clock.release = delete_ptp_clock;
        ptp->info = info;
        ptp->devid = MKDEV(major, index);
        ptp->index = index;
@@ -249,15 +248,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
        if (err)
                goto no_pin_groups;
 
-       /* Create a new device in our class. */
-       ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
-                                            ptp, ptp->pin_attr_groups,
-                                            "ptp%d", ptp->index);
-       if (IS_ERR(ptp->dev)) {
-               err = PTR_ERR(ptp->dev);
-               goto no_device;
-       }
-
        /* Register a new PPS source. */
        if (info->pps) {
                struct pps_source_info pps;
@@ -273,8 +263,18 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
                }
        }
 
-       /* Create a posix clock. */
-       err = posix_clock_register(&ptp->clock, ptp->devid);
+       /* Initialize a new device of our class in our clock structure. */
+       device_initialize(&ptp->dev);
+       ptp->dev.devt = ptp->devid;
+       ptp->dev.class = ptp_class;
+       ptp->dev.parent = parent;
+       ptp->dev.groups = ptp->pin_attr_groups;
+       ptp->dev.release = ptp_clock_release;
+       dev_set_drvdata(&ptp->dev, ptp);
+       dev_set_name(&ptp->dev, "ptp%d", ptp->index);
+
+       /* Create a posix clock and link it to the device. */
+       err = posix_clock_register(&ptp->clock, &ptp->dev);
        if (err) {
                pr_err("failed to create posix clock\n");
                goto no_clock;
@@ -286,8 +286,6 @@ no_clock:
        if (ptp->pps_source)
                pps_unregister_source(ptp->pps_source);
 no_pps:
-       device_destroy(ptp_class, ptp->devid);
-no_device:
        ptp_cleanup_pin_groups(ptp);
 no_pin_groups:
        if (ptp->kworker)
@@ -317,7 +315,6 @@ int ptp_clock_unregister(struct ptp_clock *ptp)
        if (ptp->pps_source)
                pps_unregister_source(ptp->pps_source);
 
-       device_destroy(ptp_class, ptp->devid);
        ptp_cleanup_pin_groups(ptp);
 
        posix_clock_unregister(&ptp->clock);