diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index 4f15eb951039..00499d6fa748 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c @@ -316,6 +316,14 @@ int roccat_connect(const struct class *klass, struct hid_device *hid, int report if (!device) return -ENOMEM; + init_waitqueue_head(&device->wait); + INIT_LIST_HEAD(&device->readers); + mutex_init(&device->readers_lock); + mutex_init(&device->cbuf_lock); + device->hid = hid; + device->exist = 1; + device->cbuf_end = 0; + device->report_size = report_size; mutex_lock(&devices_lock); for (minor = 0; minor < ROCCAT_MAX_DEVICES; ++minor) { @@ -324,37 +332,30 @@ int roccat_connect(const struct class *klass, struct hid_device *hid, int report break; } - if (minor < ROCCAT_MAX_DEVICES) { - devices[minor] = device; - } else { + if (minor >= ROCCAT_MAX_DEVICES) { mutex_unlock(&devices_lock); kfree(device); return -EINVAL; } + device->minor = minor; + device->dev = device_create(klass, &hid->dev, MKDEV(roccat_major, minor), NULL, "%s%s%d", "roccat", hid->driver->name, minor); if (IS_ERR(device->dev)) { - devices[minor] = NULL; mutex_unlock(&devices_lock); temp = PTR_ERR(device->dev); kfree(device); return temp; } - mutex_unlock(&devices_lock); + /* Only publish once fully initialized, so roccat_open()/ + * roccat_disconnect() never see a half-built device. */ + devices[minor] = device; - init_waitqueue_head(&device->wait); - INIT_LIST_HEAD(&device->readers); - mutex_init(&device->readers_lock); - mutex_init(&device->cbuf_lock); - device->minor = minor; - device->hid = hid; - device->exist = 1; - device->cbuf_end = 0; - device->report_size = report_size; + mutex_unlock(&devices_lock); return minor; } @@ -369,15 +370,12 @@ void roccat_disconnect(int minor) mutex_lock(&devices_lock); device = devices[minor]; - mutex_unlock(&devices_lock); device->exist = 0; /* TODO exist maybe not needed */ device_destroy(device->dev->class, MKDEV(roccat_major, minor)); - mutex_lock(&devices_lock); devices[minor] = NULL; - mutex_unlock(&devices_lock); if (device->open) { hid_hw_close(device->hid); @@ -385,6 +383,8 @@ void roccat_disconnect(int minor) } else { roccat_free_device(device); } + + mutex_unlock(&devices_lock); } EXPORT_SYMBOL_GPL(roccat_disconnect);