aboutsummaryrefslogtreecommitdiff
path: root/net/dccp/ccid.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 07:30:19 +0200
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 07:45:31 +0200
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 330372a1a0b..e3fb52b4f5c 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -196,22 +196,41 @@ int ccid_unregister(struct ccid_operations *ccid_ops)
EXPORT_SYMBOL_GPL(ccid_unregister);
+/**
+ * ccid_request_module - Pre-load CCID module for later use
+ * This should be called only from process context (e.g. during connection
+ * setup) and is necessary for later calls to ccid_new (typically in software
+ * interrupt), so that it has the modules available when they are needed.
+ */
+static int ccid_request_module(u8 id)
+{
+ if (!in_atomic()) {
+ ccids_read_lock();
+ if (ccids[id] == NULL) {
+ ccids_read_unlock();
+ return request_module("net-dccp-ccid-%d", id);
+ }
+ ccids_read_unlock();
+ }
+ return 0;
+}
+
+int ccid_request_modules(u8 const *ccid_array, u8 array_len)
+{
+#ifdef CONFIG_KMOD
+ while (array_len--)
+ if (ccid_request_module(ccid_array[array_len]))
+ return -1;
+#endif
+ return 0;
+}
+
struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp)
{
struct ccid_operations *ccid_ops;
struct ccid *ccid = NULL;
ccids_read_lock();
-#ifdef CONFIG_KMOD
- if (ccids[id] == NULL) {
- /* We only try to load if in process context */
- ccids_read_unlock();
- if (gfp & GFP_ATOMIC)
- goto out;
- request_module("net-dccp-ccid-%d", id);
- ccids_read_lock();
- }
-#endif
ccid_ops = ccids[id];
if (ccid_ops == NULL)
goto out_unlock;