blob: 2ea50e82de803ee44c475dca65de65adfa96cafd [file] [log] [blame]
/*
* <-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/device.h>
#include "mc_kernel_api.h"
#include "public/mobicore_driver_api.h"
#include "session.h"
struct bulk_buffer_descriptor *bulk_buffer_descriptor_create(
void *virt_addr, uint32_t len, uint32_t handle)
{
struct bulk_buffer_descriptor *desc;
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
if (desc == NULL) {
MCDRV_DBG_ERROR(mc_kapi, "Allocation failure");
return NULL;
}
desc->virt_addr = virt_addr;
desc->len = len;
desc->handle = handle;
return desc;
}
struct session *session_create(
uint32_t session_id, void *instance, struct connection *connection)
{
struct session *session;
session = kzalloc(sizeof(*session), GFP_KERNEL);
if (session == NULL) {
MCDRV_DBG_ERROR(mc_kapi, "Allocation failure");
return NULL;
}
session->session_id = session_id;
session->instance = instance;
session->notification_connection = connection;
session->session_info.last_error = SESSION_ERR_NO;
session->session_info.state = SESSION_STATE_INITIAL;
INIT_LIST_HEAD(&(session->bulk_buffer_descriptors));
return session;
}
void session_cleanup(struct session *session)
{
struct bulk_buffer_descriptor *bulk_buf_descr;
struct list_head *pos, *q;
/* Unmap still mapped buffers */
list_for_each_safe(pos, q, &session->bulk_buffer_descriptors) {
bulk_buf_descr =
list_entry(pos, struct bulk_buffer_descriptor, list);
MCDRV_DBG_VERBOSE(mc_kapi,
"handle= %d",
bulk_buf_descr->handle);
/* ignore any error, as we cannot do anything in this case. */
int ret = mobicore_unmap_vmem(session->instance,
bulk_buf_descr->handle);
if (ret != 0)
MCDRV_DBG_ERROR(mc_kapi,
"mobicore_unmap_vmem failed: %d", ret);
list_del(pos);
kfree(bulk_buf_descr);
}
/* Finally delete notification connection */
connection_cleanup(session->notification_connection);
kfree(session);
}
void session_set_error_info(struct session *session, int32_t err)
{
session->session_info.last_error = err;
}
int32_t session_get_last_err(struct session *session)
{
return session->session_info.last_error;
}
struct bulk_buffer_descriptor *session_add_bulk_buf(struct session *session,
void *buf, uint32_t len)
{
struct bulk_buffer_descriptor *bulk_buf_descr = NULL;
struct bulk_buffer_descriptor *tmp;
struct list_head *pos;
/*
* Search bulk buffer descriptors for existing vAddr
* At the moment a virtual address can only be added one time
*/
list_for_each(pos, &session->bulk_buffer_descriptors) {
tmp = list_entry(pos, struct bulk_buffer_descriptor, list);
if (tmp->virt_addr == buf)
return NULL;
}
do {
/*
* Prepare the interface structure for memory registration in
* Kernel Module
*/
uint32_t handle;
int ret = mobicore_map_vmem(session->instance, buf, len,
&handle);
if (ret != 0) {
MCDRV_DBG_ERROR(mc_kapi,
"mobicore_map_vmem failed, ret=%d",
ret);
break;
}
MCDRV_DBG_VERBOSE(mc_kapi, "handle=%d", handle);
/* Create new descriptor */
bulk_buf_descr =
bulk_buffer_descriptor_create(buf, len, handle);
if (bulk_buf_descr == NULL) {
mobicore_unmap_vmem(session->instance, handle);
break;
}
/* Add to vector of descriptors */
list_add_tail(&(bulk_buf_descr->list),
&(session->bulk_buffer_descriptors));
} while (0);
return bulk_buf_descr;
}
bool session_remove_bulk_buf(struct session *session, void *virt_addr)
{
bool ret = true;
struct bulk_buffer_descriptor *bulk_buf = NULL;
struct bulk_buffer_descriptor *tmp;
struct list_head *pos, *q;
MCDRV_DBG_VERBOSE(mc_kapi, "Virtual Address = 0x%X",
(unsigned int) virt_addr);
/* Search and remove bulk buffer descriptor */
list_for_each_safe(pos, q, &session->bulk_buffer_descriptors) {
tmp = list_entry(pos, struct bulk_buffer_descriptor, list);
if (tmp->virt_addr == virt_addr) {
bulk_buf = tmp;
list_del(pos);
break;
}
}
if (bulk_buf == NULL) {
MCDRV_DBG_ERROR(mc_kapi, "Virtual Address not found");
ret = false;
} else {
MCDRV_DBG_VERBOSE(mc_kapi, "Wsm handle=%d",
bulk_buf->handle);
/* ignore any error, as we cannot do anything */
int ret = mobicore_unmap_vmem(session->instance,
bulk_buf->handle);
if (ret != 0)
MCDRV_DBG_ERROR(mc_kapi,
"mobicore_unmap_vmem failed: %d", ret);
kfree(bulk_buf);
}
return ret;
}
uint32_t session_find_bulk_buf(struct session *session, void *virt_addr)
{
struct bulk_buffer_descriptor *tmp;
struct list_head *pos, *q;
MCDRV_DBG_VERBOSE(mc_kapi, "Virtual Address = 0x%X",
(unsigned int) virt_addr);
/* Search and return buffer descriptor handle */
list_for_each_safe(pos, q, &session->bulk_buffer_descriptors) {
tmp = list_entry(pos, struct bulk_buffer_descriptor, list);
if (tmp->virt_addr == virt_addr)
return tmp->handle;
}
return 0;
}