diff options
author | Alessandro Rubini <rubini@gnudd.com> | 2013-07-16 12:58:01 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-24 22:56:52 -0700 |
commit | 783c2fb1b8ba2f057a26f881aa452d4aa8e4b3f4 (patch) | |
tree | 13f18c989ccb4e748b8db58532faf24450b5c958 /drivers/fmc/fmc-chardev.c | |
parent | 5f90b9b484938f7466e25cd5506e86ebf9dbcd17 (diff) | |
download | talos-obmc-linux-783c2fb1b8ba2f057a26f881aa452d4aa8e4b3f4.tar.gz talos-obmc-linux-783c2fb1b8ba2f057a26f881aa452d4aa8e4b3f4.zip |
FMC: fix locking in sample chardev driver
The fmc-chardev module was over-locking, by calling misc
register/unregister while holding its spinlock. This reported a
"scheduling while atomic" error.
Since the misc driver already serializes operations internally, this
commit downgrades the fmc-chardev lock to just cover its own list.
Reported-by: Sasha Levin <sasha.levin@oracle.com>
Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/fmc/fmc-chardev.c')
-rw-r--r-- | drivers/fmc/fmc-chardev.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/drivers/fmc/fmc-chardev.c b/drivers/fmc/fmc-chardev.c index cc031db2d2a3..ace6ef24d15e 100644 --- a/drivers/fmc/fmc-chardev.c +++ b/drivers/fmc/fmc-chardev.c @@ -143,18 +143,17 @@ static int fc_probe(struct fmc_device *fmc) fc->misc.fops = &fc_fops; fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL); - spin_lock(&fc_lock); ret = misc_register(&fc->misc); if (ret < 0) - goto err_unlock; + goto out; + spin_lock(&fc_lock); list_add(&fc->list, &fc_devices); spin_unlock(&fc_lock); dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n", fc->misc.name); return 0; -err_unlock: - spin_unlock(&fc_lock); +out: kfree(fc->misc.name); kfree(fc); return ret; @@ -174,10 +173,10 @@ static int fc_remove(struct fmc_device *fmc) spin_lock(&fc_lock); list_del(&fc->list); + spin_unlock(&fc_lock); misc_deregister(&fc->misc); kfree(fc->misc.name); kfree(fc); - spin_unlock(&fc_lock); return 0; } |