aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ccid.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:30:19 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:45:31 -0400
commit09856c108956c99088ead9267ccbd1dab77f7043 (patch)
tree39e29187c87429530f83d3aa672ec5b6214c8136 /net/dccp/ccid.c
parent5d3dac267a7fd0811ec777e76a81f97f5cdcb395 (diff)
dccp: Auto-load (when supported) CCID plugins for negotiation
This adds auto-loading of CCIDs (when module loading is enabled) for the purpose of feature negotiation. The problem with loading the CCIDs at the end of feature negotiation is that this would happen in software interrupt context. Besides, if the host advertises CCIDs during negotiation, it should have them ready to use, in case an agreeing peer wants to use it for the connection. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Diffstat (limited to 'net/dccp/ccid.c')
-rw-r--r--net/dccp/ccid.c39
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
197EXPORT_SYMBOL_GPL(ccid_unregister); 197EXPORT_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 */
205static 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
218int 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
199struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp) 228struct 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;