summaryrefslogtreecommitdiffstats
path: root/ncr-storage-low.c
diff options
context:
space:
mode:
Diffstat (limited to 'ncr-storage-low.c')
-rw-r--r--ncr-storage-low.c165
1 files changed, 118 insertions, 47 deletions
diff --git a/ncr-storage-low.c b/ncr-storage-low.c
index 418bc8ff969..489aa2ecfe4 100644
--- a/ncr-storage-low.c
+++ b/ncr-storage-low.c
@@ -60,6 +60,7 @@ struct event_item_st* item;
item->id = id;
item->reply = NULL;
item->reply_size = 0;
+ item->ireply = -1;
init_completion(&item->completed);
down(&event_list.sem);
@@ -73,10 +74,8 @@ static int event_wait(uint32_t id)
{
struct event_item_st* item;
struct completion* completed = NULL;
-int ret = 0;
down(&event_list.sem);
-
list_for_each_entry(item, &event_list.list, list) {
if (id == item->id) {
completed = &item->completed;
@@ -84,10 +83,13 @@ int ret = 0;
}
}
up(&event_list.sem);
+
if (completed) {
- ret = wait_for_completion_interruptible(completed);
+ return wait_for_completion_interruptible(completed);
+ } else {
+ err();
+ return -EIO;
}
- return 0;
}
@@ -203,23 +205,73 @@ struct event_item_st* item, *tmp;
static struct nla_policy ncr_genl_policy[ATTR_MAX + 1] = {
[ATTR_STRUCT_LOAD] = { .type = NLA_BINARY },
[ATTR_STRUCT_LOADED] = { .type = NLA_BINARY },
- [ATTR_STORE_ACK] = { .type = NLA_BINARY },
+ [ATTR_STORE_U8] = { .type = NLA_BINARY },
[ATTR_STRUCT_STORE] = { .type = NLA_BINARY },
};
static atomic_t ncr_event_sr;
static uint32_t listener_pid = -1;
-#define VERSION_NR 1
/* family definition */
static struct genl_family ncr_gnl_family = {
.id = GENL_ID_GENERATE, //genetlink should generate an id
.hdrsize = 0,
.name = NCR_NL_STORAGE_NAME, //the name of this family, used by userspace application
- .version = VERSION_NR, //version number
+ .version = NCR_NL_STORAGE_VERSION, //version number
.maxattr = ATTR_MAX,
};
+/* an echo command, receives a message, prints it and sends another message back */
+static void _ncr_nl_close(void)
+{
+ struct sk_buff *skb;
+ int ret;
+ void *msg_head;
+ uint32_t id;
+
+ if (listener_pid == -1) {
+ err();
+ return;
+ }
+
+ skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (skb == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ id = atomic_add_return(1, &ncr_event_sr);
+ msg_head = genlmsg_put(skb, 0, id, &ncr_gnl_family, 0, CMD_CLOSE);
+ if (msg_head == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = nla_put_u8(skb, ATTR_STORE_U8, 1);
+ if (ret != 0) {
+ err();
+ goto out;
+ }
+
+ /* finalize the message */
+ genlmsg_end(skb, msg_head);
+
+ /* send the message back */
+ ret = genlmsg_unicast(skb, listener_pid);
+ if (ret != 0) {
+ err();
+ goto out;
+ }
+
+ return;
+
+out:
+ nlmsg_free(skb);
+ printk("an error occured in ncr_gnl_store\n");
+
+ return;
+}
/* an echo command, receives a message, prints it and sends another message back */
int _ncr_store(const struct storage_item_st * tostore)
@@ -236,7 +288,7 @@ int _ncr_store(const struct storage_item_st * tostore)
err();
return -EIO;
}
-
+
/* send a message back*/
/* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE*/
size = nla_total_size(sizeof(struct storage_item_st)) +
@@ -248,7 +300,7 @@ int _ncr_store(const struct storage_item_st * tostore)
goto out;
}
- id = atomic_long_inc_return(&ncr_event_sr);
+ id = atomic_add_return(1, &ncr_event_sr);
msg_head = genlmsg_put(skb, 0, id,
&ncr_gnl_family, 0, CMD_STORE);
if (msg_head == NULL) {
@@ -278,6 +330,12 @@ int _ncr_store(const struct storage_item_st * tostore)
/* finalize the message */
genlmsg_end(skb, msg_head);
+ ret = event_add(id);
+ if (ret < 0) {
+ err();
+ goto out;
+ }
+
/* send the message back */
ret = genlmsg_unicast(skb, listener_pid);
if (ret != 0)
@@ -286,10 +344,13 @@ int _ncr_store(const struct storage_item_st * tostore)
/* wait for an acknowledgment */
ret = event_wait(id);
if (ret) {
- goto out;
+ err();
+ printk(KERN_DEBUG"Error waiting for id %u\n", id);
+ event_remove(id);
+ return ret;
}
- reply = event_get_idata(id, &reply_size);
+ reply = event_get_idata(id);
if (reply == (uint32_t)-1)
BUG();
@@ -317,7 +378,7 @@ int _ncr_load(struct storage_item_st * toload)
struct sk_buff *skb;
int ret;
void *msg_head;
- size_t size, reply_size;
+ size_t reply_size=0, size;
struct nlattr *attr;
void* msg, *reply;
struct ncr_gnl_load_cmd_st cmd;
@@ -339,7 +400,7 @@ int _ncr_load(struct storage_item_st * toload)
goto out;
}
- id = atomic_long_inc_return(&ncr_event_sr);
+ id = atomic_add_return(1, &ncr_event_sr);
msg_head = genlmsg_put(skb, 0, id,
&ncr_gnl_family, 0, CMD_LOAD);
if (msg_head == NULL) {
@@ -386,7 +447,10 @@ int _ncr_load(struct storage_item_st * toload)
/* wait for an answer */
ret = event_wait(id);
if (ret) {
- goto out;
+ err();
+ printk(KERN_DEBUG"Error waiting for id %u\n", id);
+ event_remove(id);
+ return ret;
}
reply = event_get_data(id, &reply_size);
@@ -413,6 +477,8 @@ int ncr_gnl_listen(struct sk_buff *skb, struct genl_info *info)
return -EIO;
listener_pid = info->snd_pid;
+ atomic_set(&ncr_event_sr, info->snd_seq+1);
+ printk(KERN_DEBUG"Setting listener pid to %d!\n", (int)listener_pid);
return 0;
}
@@ -421,33 +487,32 @@ int ncr_gnl_listen(struct sk_buff *skb, struct genl_info *info)
/* with this command the userspace server registers */
int ncr_gnl_store_ack(struct sk_buff *skb, struct genl_info *info)
{
- uint8_t * data, *event_reply;
+ uint8_t * data;
size_t len;
- struct ncr_gnl_store_ack_st reply;
+ struct ncr_gnl_store_ack_st *reply;
struct nlattr *na;
if (info == NULL)
return -EIO;
+ printk("Received store ack!\n");
/*for each attribute there is an index in info->attrs which points to a nlattr structure
*in this structure the data is given
*/
- na = info->attrs[ATTR_STORE_ACK];
+ na = info->attrs[ATTR_STORE_U8];
if (na) {
len = nla_len(na);
data = (void *)nla_data(na);
if (data == NULL || len != sizeof(struct ncr_gnl_store_ack_st))
printk(KERN_DEBUG"error while receiving data\n");
else {
-
- memcpy( &reply, data, sizeof(reply));
-
- event_set_idata(reply.id, (uint32_t)reply.reply[0]);
+ reply = (void*)data;
+ event_set_idata(reply->id, (uint32_t)reply->reply);
- event_complete(reply.id);
+ event_complete(reply->id);
}
} else
- printk(KERN_DEBUG"no info->attrs %i\n", ATTR_STORE_ACK);
+ printk(KERN_DEBUG"no info->attrs %i\n", ATTR_STORE_U8);
return 0;
}
@@ -457,7 +522,7 @@ int ncr_gnl_loaded_data(struct sk_buff *skb, struct genl_info *info)
{
uint8_t * data, *event_reply;
size_t len;
- struct ncr_gnl_loaded_st reply;
+ struct ncr_gnl_loaded_st *reply;
struct nlattr *na;
if (info == NULL)
@@ -473,14 +538,13 @@ int ncr_gnl_loaded_data(struct sk_buff *skb, struct genl_info *info)
if (data == NULL || len != sizeof(struct ncr_gnl_loaded_st))
printk(KERN_DEBUG"error while receiving data\n");
else {
-
- memcpy( &reply, data, sizeof(reply));
- event_reply = kmalloc(sizeof(reply.storage), GFP_KERNEL);
+ reply = (void*)data;
+ event_reply = kmalloc(sizeof(reply->storage), GFP_KERNEL);
if (event_reply != NULL) {
- memcpy(event_reply, &reply.storage, sizeof(reply.storage));
- event_set_data(reply.id, event_reply, sizeof(reply.storage));
+ memcpy(event_reply, &reply->storage, sizeof(reply->storage));
+ event_set_data(reply->id, event_reply, sizeof(reply->storage));
}
- event_complete(reply.id);
+ event_complete(reply->id);
}
} else
printk(KERN_DEBUG"no info->attrs %i\n", ATTR_STRUCT_LOADED);
@@ -519,35 +583,38 @@ struct genl_ops ncr_gnl_ops_store_ack = {
int ncr_gnl_init(void)
{
int rc;
- printk("INIT GENERIC NETLINK EXEMPLE MODULE\n");
+
+ printk(KERN_NOTICE"cryptodev: Initializing netlink subsystem.\n");
init_MUTEX(&event_list.sem);
INIT_LIST_HEAD(&event_list.list);
- atomic_set(&ncr_event_sr, 0);
+ atomic_set(&ncr_event_sr, 1);
- /*register new family*/
+ /*register new family*/
rc = genl_register_family(&ncr_gnl_family);
- if (rc != 0)
+ if (rc != 0) {
+ err();
goto failure;
- /*register functions (commands) of the new family*/
+ }
+ /*register functions (commands) of the new family*/
rc = genl_register_ops(&ncr_gnl_family, &ncr_gnl_ops_listen);
if (rc != 0) {
- printk("register ops: %i\n",rc);
+ err();
genl_unregister_family(&ncr_gnl_family);
goto failure;
}
rc = genl_register_ops(&ncr_gnl_family, &ncr_gnl_ops_store_ack);
if (rc != 0) {
- printk("register ops: %i\n",rc);
+ err();
genl_unregister_family(&ncr_gnl_family);
goto failure;
}
rc = genl_register_ops(&ncr_gnl_family, &ncr_gnl_ops_load);
if (rc != 0) {
- printk("register ops: %i\n",rc);
+ err();
genl_unregister_family(&ncr_gnl_family);
goto failure;
}
@@ -555,7 +622,7 @@ int ncr_gnl_init(void)
return 0;
failure:
- printk("an error occured while inserting the generic netlink example module\n");
+ printk(KERN_ERR"an error occured while loading the cryptodev netlink subsystem\n");
return rc;
}
@@ -563,15 +630,8 @@ void ncr_gnl_deinit(void)
{
int ret;
struct event_item_st *item, *tmp;
- printk("EXIT GENERIC NETLINK EXEMPLE MODULE\n");
- /* deinitialize the event list */
- down(&event_list.sem);
- list_for_each_entry_safe(item, tmp, &event_list.list, list) {
- list_del(&item->list);
- kfree(item);
- }
- up(&event_list.sem);
+ _ncr_nl_close();
ret = genl_unregister_ops(&ncr_gnl_family, &ncr_gnl_ops_store_ack);
if(ret != 0) {
@@ -596,4 +656,15 @@ void ncr_gnl_deinit(void)
if(ret !=0) {
printk("unregister family %i\n",ret);
}
+
+ /* deinitialize the event list */
+ down(&event_list.sem);
+ list_for_each_entry_safe(item, tmp, &event_list.list, list) {
+ list_del(&item->list);
+ if (item->reply)
+ kfree(item->reply);
+ kfree(item);
+ }
+ up(&event_list.sem);
+
}