diff options
author | Alessandro Rubini <rubini@gnudd.com> | 2013-07-16 06:58:01 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-25 01:56:52 -0400 |
commit | 783c2fb1b8ba2f057a26f881aa452d4aa8e4b3f4 (patch) | |
tree | 13f18c989ccb4e748b8db58532faf24450b5c958 /drivers/fmc | |
parent | 5f90b9b484938f7466e25cd5506e86ebf9dbcd17 (diff) |
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')
-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) | |||
143 | fc->misc.fops = &fc_fops; | 143 | fc->misc.fops = &fc_fops; |
144 | fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL); | 144 | fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL); |
145 | 145 | ||
146 | spin_lock(&fc_lock); | ||
147 | ret = misc_register(&fc->misc); | 146 | ret = misc_register(&fc->misc); |
148 | if (ret < 0) | 147 | if (ret < 0) |
149 | goto err_unlock; | 148 | goto out; |
149 | spin_lock(&fc_lock); | ||
150 | list_add(&fc->list, &fc_devices); | 150 | list_add(&fc->list, &fc_devices); |
151 | spin_unlock(&fc_lock); | 151 | spin_unlock(&fc_lock); |
152 | dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n", | 152 | dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n", |
153 | fc->misc.name); | 153 | fc->misc.name); |
154 | return 0; | 154 | return 0; |
155 | 155 | ||
156 | err_unlock: | 156 | out: |
157 | spin_unlock(&fc_lock); | ||
158 | kfree(fc->misc.name); | 157 | kfree(fc->misc.name); |
159 | kfree(fc); | 158 | kfree(fc); |
160 | return ret; | 159 | return ret; |
@@ -174,10 +173,10 @@ static int fc_remove(struct fmc_device *fmc) | |||
174 | 173 | ||
175 | spin_lock(&fc_lock); | 174 | spin_lock(&fc_lock); |
176 | list_del(&fc->list); | 175 | list_del(&fc->list); |
176 | spin_unlock(&fc_lock); | ||
177 | misc_deregister(&fc->misc); | 177 | misc_deregister(&fc->misc); |
178 | kfree(fc->misc.name); | 178 | kfree(fc->misc.name); |
179 | kfree(fc); | 179 | kfree(fc); |
180 | spin_unlock(&fc_lock); | ||
181 | 180 | ||
182 | return 0; | 181 | return 0; |
183 | } | 182 | } |