diff options
Diffstat (limited to 'net/dccp/ccid.c')
-rw-r--r-- | net/dccp/ccid.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c index 330372a1a0b6..e3fb52b4f5c6 100644 --- a/net/dccp/ccid.c +++ b/net/dccp/ccid.c | |||
@@ -196,22 +196,41 @@ int ccid_unregister(struct ccid_operations *ccid_ops) | |||
196 | 196 | ||
197 | EXPORT_SYMBOL_GPL(ccid_unregister); | 197 | EXPORT_SYMBOL_GPL(ccid_unregister); |
198 | 198 | ||
199 | /** | ||
200 | * ccid_request_module - Pre-load CCID module for later use | ||
201 | * This should be called only from process context (e.g. during connection | ||
202 | * setup) and is necessary for later calls to ccid_new (typically in software | ||
203 | * interrupt), so that it has the modules available when they are needed. | ||
204 | */ | ||
205 | static int ccid_request_module(u8 id) | ||
206 | { | ||
207 | if (!in_atomic()) { | ||
208 | ccids_read_lock(); | ||
209 | if (ccids[id] == NULL) { | ||
210 | ccids_read_unlock(); | ||
211 | return request_module("net-dccp-ccid-%d", id); | ||
212 | } | ||
213 | ccids_read_unlock(); | ||
214 | } | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | int ccid_request_modules(u8 const *ccid_array, u8 array_len) | ||
219 | { | ||
220 | #ifdef CONFIG_KMOD | ||
221 | while (array_len--) | ||
222 | if (ccid_request_module(ccid_array[array_len])) | ||
223 | return -1; | ||
224 | #endif | ||
225 | return 0; | ||
226 | } | ||
227 | |||
199 | struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp) | 228 | struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp) |
200 | { | 229 | { |
201 | struct ccid_operations *ccid_ops; | 230 | struct ccid_operations *ccid_ops; |
202 | struct ccid *ccid = NULL; | 231 | struct ccid *ccid = NULL; |
203 | 232 | ||
204 | ccids_read_lock(); | 233 | ccids_read_lock(); |
205 | #ifdef CONFIG_KMOD | ||
206 | if (ccids[id] == NULL) { | ||
207 | /* We only try to load if in process context */ | ||
208 | ccids_read_unlock(); | ||
209 | if (gfp & GFP_ATOMIC) | ||
210 | goto out; | ||
211 | request_module("net-dccp-ccid-%d", id); | ||
212 | ccids_read_lock(); | ||
213 | } | ||
214 | #endif | ||
215 | ccid_ops = ccids[id]; | 234 | ccid_ops = ccids[id]; |
216 | if (ccid_ops == NULL) | 235 | if (ccid_ops == NULL) |
217 | goto out_unlock; | 236 | goto out_unlock; |