aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorGravatar Greg Kroah-Hartman <greg@kroah.com> 2014-12-24 13:01:40 -0800
committerGravatar Greg Kroah-Hartman <greg@kroah.com> 2015-01-02 13:05:42 -0800
commit12a5dfc9acf690504e7266a8f310702bc9e6872c (patch)
treee08322fe107b8caed9adb4f7a678ea582ea4727f /drivers/staging
parentgreybus: bundle: create GB_DEVICE_ID_BAD (diff)
downloadlinux-12a5dfc9acf690504e7266a8f310702bc9e6872c.tar.gz
linux-12a5dfc9acf690504e7266a8f310702bc9e6872c.tar.bz2
linux-12a5dfc9acf690504e7266a8f310702bc9e6872c.zip
greybus: protocol: add a module owner to a protocol
Now that protocols can be in a module, we need to reference count them to lock them into memory so they can't be removed while in use. So add a module owner structure, and have it automatically be assigned when registering the protocol. Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> Reviewed-by: Alex Elder <elder@linaro.org>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/greybus/protocol.c17
-rw-r--r--drivers/staging/greybus/protocol.h6
2 files changed, 17 insertions, 6 deletions
diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c
index ee8ee3e15f8e..c6c0fd3ebea3 100644
--- a/drivers/staging/greybus/protocol.c
+++ b/drivers/staging/greybus/protocol.c
@@ -39,13 +39,15 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor)
return NULL;
}
-int gb_protocol_register(struct gb_protocol *protocol)
+int __gb_protocol_register(struct gb_protocol *protocol, struct module *module)
{
struct gb_protocol *existing;
u8 id = protocol->id;
u8 major = protocol->major;
u8 minor = protocol->minor;
+ protocol->owner = module;
+
/*
* The protocols list is sorted first by protocol id (low to
* high), then by major version (high to low), and finally
@@ -92,7 +94,7 @@ int gb_protocol_register(struct gb_protocol *protocol)
return 0;
}
-EXPORT_SYMBOL_GPL(gb_protocol_register);
+EXPORT_SYMBOL_GPL(__gb_protocol_register);
/*
* De-register a previously registered protocol.
@@ -135,9 +137,13 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor)
spin_lock_irq(&gb_protocols_lock);
protocol = _gb_protocol_find(id, major, minor);
if (protocol) {
- protocol_count = protocol->count;
- if (protocol_count != U8_MAX)
- protocol->count++;
+ if (!try_module_get(protocol->owner)) {
+ protocol = NULL;
+ } else {
+ protocol_count = protocol->count;
+ if (protocol_count != U8_MAX)
+ protocol->count++;
+ }
}
spin_unlock_irq(&gb_protocols_lock);
@@ -163,6 +169,7 @@ void gb_protocol_put(struct gb_protocol *protocol)
protocol_count = protocol->count;
if (protocol_count)
protocol->count--;
+ module_put(protocol->owner);
}
spin_unlock_irq(&gb_protocols_lock);
if (protocol)
diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h
index e2555b75e334..62f024dd71bd 100644
--- a/drivers/staging/greybus/protocol.h
+++ b/drivers/staging/greybus/protocol.h
@@ -34,11 +34,15 @@ struct gb_protocol {
gb_connection_init_t connection_init;
gb_connection_exit_t connection_exit;
gb_request_recv_t request_recv;
+ struct module *owner;
};
-int gb_protocol_register(struct gb_protocol *protocol);
+int __gb_protocol_register(struct gb_protocol *protocol, struct module *module);
int gb_protocol_deregister(struct gb_protocol *protocol);
+#define gb_protocol_register(protocol) \
+ __gb_protocol_register(protocol, THIS_MODULE)
+
struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor);
void gb_protocol_put(struct gb_protocol *protocol);