From: Tim Sell <Timothy.Sell@xxxxxxxxxx> This is NOT technically required for the code as it stands now, but will be needed for subsequent patches. Signed-off-by: Tim Sell <Timothy.Sell@xxxxxxxxxx> Signed-off-by: Benjamin Romer <benjamin.romer@xxxxxxxxxx> --- v2: resources are released in the reverse order they were acquired, as per Dan Carpenter's comment. --- drivers/staging/unisys/visorinput/visorinput.c | 45 ++++++++++++++++++++------ 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 5c16f66..238a132 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -62,6 +62,7 @@ enum visorinput_device_type { * dev_get_drvdata() / dev_set_drvdata() for each struct device. */ struct visorinput_devdata { + struct kref kref; struct visor_device *dev; struct rw_semaphore lock_visor_dev; /* lock for dev */ struct input_dev *visorinput_dev; @@ -346,6 +347,35 @@ register_client_mouse(void *devdata /* opaque on purpose */) return visorinput_dev; } +static void +unregister_client_input(struct input_dev *visorinput_dev) +{ + if (visorinput_dev) + input_unregister_device(visorinput_dev); +} + +static void devdata_release(struct kref *kref) +{ + struct visorinput_devdata *devdata = + container_of(kref, struct visorinput_devdata, kref); + unregister_client_input(devdata->visorinput_dev); + kfree(devdata); +} + +static struct visorinput_devdata * +devdata_get(struct visorinput_devdata *devdata) +{ + if (devdata) + kref_get(&devdata->kref); + return devdata; +} + +static void devdata_put(struct visorinput_devdata *devdata) +{ + if (devdata) + kref_put(&devdata->kref, devdata_release); +} + static struct visorinput_devdata * devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) { @@ -385,6 +415,7 @@ devdata_create(struct visor_device *dev, enum visorinput_device_type devtype) } init_rwsem(&devdata->lock_visor_dev); + kref_init(&devdata->kref); return devdata; @@ -415,13 +446,6 @@ visorinput_probe(struct visor_device *dev) } static void -unregister_client_input(struct input_dev *visorinput_dev) -{ - if (visorinput_dev) - input_unregister_device(visorinput_dev); -} - -static void visorinput_remove(struct visor_device *dev) { struct visorinput_devdata *devdata = dev_get_drvdata(&dev->device); @@ -438,9 +462,8 @@ visorinput_remove(struct visor_device *dev) down_write(&devdata->lock_visor_dev); dev_set_drvdata(&dev->device, NULL); - unregister_client_input(devdata->visorinput_dev); up_write(&devdata->lock_visor_dev); - kfree(devdata); + devdata_put(devdata); } /* @@ -526,7 +549,8 @@ visorinput_channel_interrupt(struct visor_device *dev) int xmotion, ymotion, zmotion, button; int i; - struct visorinput_devdata *devdata = dev_get_drvdata(&dev->device); + struct visorinput_devdata *devdata = + devdata_get(dev_get_drvdata(&dev->device)); if (!devdata) return; @@ -617,6 +641,7 @@ visorinput_channel_interrupt(struct visor_device *dev) } out_locked: up_write(&devdata->lock_visor_dev); + devdata_put(devdata); } static int -- 2.5.0 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel