1031 lines
24 KiB
C
1031 lines
24 KiB
C
|
|
// SPDX-License-Identifier: GPL-2.0
|
||
|
|
/*
|
||
|
|
* Copyright (c) 2020 MediaTek Inc.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <linux/errno.h>
|
||
|
|
#include <linux/slab.h>
|
||
|
|
#include <linux/errno.h>
|
||
|
|
|
||
|
|
#include <linux/kernel.h>
|
||
|
|
#include <linux/io.h>
|
||
|
|
#include <linux/sched.h>
|
||
|
|
#include <linux/types.h>
|
||
|
|
|
||
|
|
#include "reviser_reg.h"
|
||
|
|
#include "reviser_cmn.h"
|
||
|
|
#include "reviser_drv.h"
|
||
|
|
#include "reviser_mem_mgt.h"
|
||
|
|
#include "reviser_hw.h"
|
||
|
|
|
||
|
|
//ONLY FOR DEBUGGING
|
||
|
|
#define _FORCE_SET_REMAP 0
|
||
|
|
|
||
|
|
|
||
|
|
//static unsigned long pgtable_dram[BITS_TO_LONGS(VLM_DRAM_BANK_MAX)];
|
||
|
|
static unsigned long table_tcm[BITS_TO_LONGS(TABLE_TCM_MAX)];
|
||
|
|
static unsigned long table_ctxID[BITS_TO_LONGS(TABLE_CTXID_MAX)];
|
||
|
|
|
||
|
|
static bool g_ctxid_empty;
|
||
|
|
static uint32_t g_tcm_free;
|
||
|
|
static struct vlm_pgtable g_vlm_pgtable[VLM_CTXT_CTX_ID_MAX];
|
||
|
|
static struct table_remap g_table_remap;
|
||
|
|
|
||
|
|
static int _reviser_set_vlm_pgtable(void *drvinfo,
|
||
|
|
unsigned long ctxID, struct table_vlm *vlm_pgtable);
|
||
|
|
static int _reviser_clear_vlm_pgtable(void *drvinfo,
|
||
|
|
unsigned long ctxID, struct table_tcm *tcm_pgtable);
|
||
|
|
static int _reviser_force_remap(void *drvinfo);
|
||
|
|
|
||
|
|
static int _reviser_force_remap(void *drvinfo)
|
||
|
|
{
|
||
|
|
int ret = 0;
|
||
|
|
/* Debug ONLY */
|
||
|
|
#if _FORCE_SET_REMAP
|
||
|
|
|
||
|
|
int valid = 0;
|
||
|
|
int ctxid = 0;
|
||
|
|
|
||
|
|
/* Set HW remap table */
|
||
|
|
if (reviser_set_remap_table(drvinfo, 0, valid, ctxid, 0, 0)) {
|
||
|
|
ret = -1;
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
if (reviser_set_remap_table(drvinfo, 1, valid, ctxid, 0, 1)) {
|
||
|
|
ret = -1;
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
if (reviser_set_remap_table(drvinfo, 2, valid, ctxid, 2, 2)) {
|
||
|
|
ret = -1;
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
if (reviser_set_remap_table(drvinfo, 3, valid, ctxid, 3, 3)) {
|
||
|
|
ret = -1;
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
if (reviser_set_remap_table(drvinfo, 4, valid, ctxid, 0, 1)) {
|
||
|
|
ret = -1;
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
if (reviser_set_remap_table(drvinfo, 5, valid, ctxid, 1, 2)) {
|
||
|
|
ret = -1;
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
if (reviser_set_remap_table(drvinfo, 6, valid, ctxid, 2, 3)) {
|
||
|
|
ret = -1;
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
if (reviser_set_remap_table(drvinfo, 7, valid, ctxid, 3, 0)) {
|
||
|
|
ret = -1;
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
out:
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
int reviser_table_init_ctxID(void *drvinfo)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_ctxid);
|
||
|
|
|
||
|
|
bitmap_zero(table_ctxID, TABLE_CTXID_MAX);
|
||
|
|
g_ctxid_empty = false;
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_ctxid);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
int reviser_table_get_ctxID_sync(void *drvinfo, unsigned long *ctxID)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
while (1) {
|
||
|
|
if (reviser_table_get_ctxID(drvinfo, ctxID)) {
|
||
|
|
LOG_DEBUG("Wait for Getting ctxID\n");
|
||
|
|
wait_event_interruptible(reviser_device->wait_ctxid,
|
||
|
|
!g_ctxid_empty);
|
||
|
|
} else {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//LOG_DEBUG("Sync Get ctxID %lu\n", *ctxID);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int reviser_table_get_ctxID(void *drvinfo, unsigned long *ctxID)
|
||
|
|
{
|
||
|
|
unsigned long fist_zero = 0;
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_ctxid);
|
||
|
|
|
||
|
|
fist_zero = find_first_zero_bit(table_ctxID, TABLE_CTXID_MAX);
|
||
|
|
if (fist_zero < TABLE_CTXID_MAX) {
|
||
|
|
bitmap_set(table_ctxID, fist_zero, 1);
|
||
|
|
|
||
|
|
*ctxID = fist_zero;
|
||
|
|
} else {
|
||
|
|
LOG_ERR("No free ctxID %lu\n", fist_zero);
|
||
|
|
g_ctxid_empty = true;
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
LOG_DEBUG("[out] ctxID(%lu) table_ctxID(%08lx)\n",
|
||
|
|
*ctxID, table_ctxID[0]);
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_ctxid);
|
||
|
|
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
free_mutex:
|
||
|
|
mutex_unlock(&reviser_device->mutex_ctxid);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int reviser_table_free_ctxID(void *drvinfo, unsigned long ctxID)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (ctxID >= TABLE_CTXID_MAX) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_ctxid);
|
||
|
|
|
||
|
|
|
||
|
|
bitmap_clear(table_ctxID, ctxID, 1);
|
||
|
|
g_ctxid_empty = false;
|
||
|
|
//LOG_DEBUG("Clear table for ctxID %lu\n", ctxID);
|
||
|
|
wake_up_interruptible(&reviser_device->wait_ctxid);
|
||
|
|
|
||
|
|
LOG_DEBUG("[in] ctxID(%lu) [out] table_ctxID(%08lx)\n"
|
||
|
|
, ctxID, table_ctxID[0]);
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_ctxid);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
}
|
||
|
|
void reviser_table_print_ctxID(void *drvinfo, void *s_file)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
uint32_t i;
|
||
|
|
struct seq_file *s = (struct seq_file *)s_file;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
mutex_lock(&reviser_device->mutex_ctxid);
|
||
|
|
|
||
|
|
LOG_CON(s, "=============================\n");
|
||
|
|
LOG_CON(s, " Contex Table\n");
|
||
|
|
LOG_CON(s, "-----------------------------\n");
|
||
|
|
|
||
|
|
for (i = 0; i < BITS_TO_LONGS(TABLE_CTXID_MAX); i++)
|
||
|
|
LOG_CON(s, "%d: [%lx]\n", i, table_ctxID[i]);
|
||
|
|
|
||
|
|
LOG_CON(s, "=============================\n");
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_ctxid);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
int reviser_table_init_tcm(void *drvinfo)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_tcm);
|
||
|
|
|
||
|
|
if (TABLE_TCM_MAX != 0)
|
||
|
|
bitmap_zero(table_tcm, TABLE_TCM_MAX);
|
||
|
|
g_tcm_free = TABLE_TCM_MAX;
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_tcm);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
int reviser_table_get_tcm_sync(void *drvinfo,
|
||
|
|
uint32_t page_num, struct table_tcm *pg_table)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (page_num > VLM_TCM_BANK_MAX) {
|
||
|
|
LOG_ERR("invalid page_num %d\n", page_num);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (pg_table == NULL) {
|
||
|
|
LOG_ERR("invalid pg_table\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
while (1) {
|
||
|
|
if (reviser_table_get_tcm(drvinfo, page_num, pg_table)) {
|
||
|
|
LOG_DEBUG("Wait for Getting tcm\n");
|
||
|
|
wait_event_interruptible(reviser_device->wait_tcm,
|
||
|
|
g_tcm_free >= page_num);
|
||
|
|
} else {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//LOG_DEBUG("Sync Get page_num %u\n", pg_table->page_num);
|
||
|
|
//LOG_DEBUG("Sync Get table_tcm %lx\n", pg_table->table_tcm[0]);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int reviser_table_get_tcm(void *drvinfo,
|
||
|
|
uint32_t page_num, struct table_tcm *tcm_pgtable)
|
||
|
|
{
|
||
|
|
unsigned long fist_zero = 0;
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
uint32_t i;
|
||
|
|
unsigned long setbits = 0;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_tcm);
|
||
|
|
|
||
|
|
// LOG_DEBUG("page_num %u tcm_pgtable %lx\n",
|
||
|
|
// page_num, tcm_pgtable->table_tcm[0]);
|
||
|
|
if (g_tcm_free == 0 || TABLE_TCM_MAX == 0) {
|
||
|
|
LOG_DEBUG("No free TCM (%u/%u)\n",
|
||
|
|
page_num, g_tcm_free);
|
||
|
|
tcm_pgtable->page_num = 0;
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
|
||
|
|
setbits = bitmap_weight(table_tcm, TABLE_TCM_MAX);
|
||
|
|
//LOG_DEBUG("setbits %lu\n", setbits);
|
||
|
|
if (TABLE_TCM_MAX - setbits < page_num) {
|
||
|
|
LOG_DEBUG("No free page (%u/%lu)\n",
|
||
|
|
page_num, TABLE_TCM_MAX - setbits);
|
||
|
|
tcm_pgtable->page_num = 0;
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 0; i < page_num; i++) {
|
||
|
|
fist_zero = find_first_zero_bit(table_tcm, TABLE_TCM_MAX);
|
||
|
|
if (fist_zero < TABLE_TCM_MAX) {
|
||
|
|
bitmap_set(table_tcm, fist_zero, 1);
|
||
|
|
bitmap_set(tcm_pgtable->table_tcm, fist_zero, 1);
|
||
|
|
g_tcm_free--;
|
||
|
|
tcm_pgtable->page_num++;
|
||
|
|
//LOG_DEBUG("page_num %lu\n", i);
|
||
|
|
//LOG_DEBUG("tcm table %lx\n", table_tcm[0]);
|
||
|
|
//LOG_DEBUG("tcm_pgtable %lx\n",
|
||
|
|
// tcm_pgtable->table_tcm[0]);
|
||
|
|
}
|
||
|
|
|
||
|
|
// else {
|
||
|
|
// LOG_ERR("No free page %lu\n", i);
|
||
|
|
// LOG_DEBUG("pg_table->table_tcm %lx\n",
|
||
|
|
// pg_table->table_tcm[0]);
|
||
|
|
// LOG_DEBUG("Before restore tcm %lx g_tcm_free %d\n",
|
||
|
|
// table_tcm[0], g_tcm_free);
|
||
|
|
// //Restore bitmap
|
||
|
|
// bitmap_andnot(table_tcm, table_tcm, pg_table->table_tcm,
|
||
|
|
// TABLE_TCM_MAX);
|
||
|
|
// g_tcm_free = g_tcm_free + pg_table->page_num;
|
||
|
|
// bitmap_zero(pg_table->table_tcm, TABLE_TCM_MAX);
|
||
|
|
// pg_table->page_num = 0;
|
||
|
|
// LOG_DEBUG("After restore tcm %lx g_tcm_free %d\n",
|
||
|
|
// table_tcm[0], g_tcm_free);
|
||
|
|
// goto free_mutex;
|
||
|
|
// }
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
LOG_DEBUG("[in] pg(%u) [out] g_tcm(%lx) g_tcm_free(%d) tcm_pgtb(%lx)\n",
|
||
|
|
page_num,
|
||
|
|
table_tcm[0], g_tcm_free, tcm_pgtable->table_tcm[0]);
|
||
|
|
mutex_unlock(&reviser_device->mutex_tcm);
|
||
|
|
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
free_mutex:
|
||
|
|
mutex_unlock(&reviser_device->mutex_tcm);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int reviser_table_free_tcm(void *drvinfo, struct table_tcm *pg_table)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (pg_table == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (pg_table->page_num == 0) {
|
||
|
|
LOG_DEBUG("[in] pg(%u) tcm_pgtb(%lx)\n",
|
||
|
|
pg_table->page_num, pg_table->table_tcm[0]);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_tcm);
|
||
|
|
|
||
|
|
|
||
|
|
if (pg_table->page_num <= TABLE_TCM_MAX) {
|
||
|
|
|
||
|
|
//LOG_DEBUG("pg_table->table_tcm %lx\n",
|
||
|
|
// pg_table->table_tcm[0]);
|
||
|
|
//LOG_DEBUG("Before restore tcm %lx g_tcm_free %d\n",
|
||
|
|
// table_tcm[0], g_tcm_free);
|
||
|
|
bitmap_andnot(table_tcm, table_tcm, pg_table->table_tcm,
|
||
|
|
TABLE_TCM_MAX);
|
||
|
|
g_tcm_free = g_tcm_free + pg_table->page_num;
|
||
|
|
//LOG_DEBUG("After restore tcm %lx g_tcm_free %d\n",
|
||
|
|
// table_tcm[0], g_tcm_free);
|
||
|
|
wake_up_interruptible(&reviser_device->wait_tcm);
|
||
|
|
} else {
|
||
|
|
LOG_ERR("Out of range %u\n", pg_table->page_num);
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
|
||
|
|
LOG_DEBUG("[in] pg(%u) tcm_pgtb(%lx) [out] g_tcm(%lx) g_tcm_free(%d)\n",
|
||
|
|
pg_table->page_num, pg_table->table_tcm[0],
|
||
|
|
table_tcm[0], g_tcm_free);
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_tcm);
|
||
|
|
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
free_mutex:
|
||
|
|
mutex_unlock(&reviser_device->mutex_tcm);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void reviser_table_print_tcm(void *drvinfo, void *s_file)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
struct seq_file *s = (struct seq_file *)s_file;
|
||
|
|
uint32_t i;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (TABLE_TCM_MAX == 0) {
|
||
|
|
LOG_DEBUG("No TCM\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
mutex_lock(&reviser_device->mutex_tcm);
|
||
|
|
|
||
|
|
LOG_CON(s, "=============================\n");
|
||
|
|
LOG_CON(s, " TCM Table\n");
|
||
|
|
LOG_CON(s, "-----------------------------\n");
|
||
|
|
|
||
|
|
for (i = 0; i < BITS_TO_LONGS(TABLE_TCM_MAX); i++)
|
||
|
|
LOG_CON(s, "%d: [%lx]\n", i, table_tcm[i]);
|
||
|
|
|
||
|
|
LOG_CON(s, "=============================\n");
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_tcm);
|
||
|
|
}
|
||
|
|
|
||
|
|
int reviser_table_init_vlm(void *drvinfo)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
memset(g_vlm_pgtable, 0,
|
||
|
|
sizeof(struct vlm_pgtable) * VLM_CTXT_CTX_ID_MAX);
|
||
|
|
reviser_device->pvlm = g_vlm_pgtable;
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
static int _reviser_set_vlm_pgtable(void *drvinfo,
|
||
|
|
unsigned long ctxID, struct table_vlm *vlm_pgtable)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
unsigned long index = 0;
|
||
|
|
uint32_t page_num;
|
||
|
|
|
||
|
|
uint32_t i;
|
||
|
|
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (ctxID >= VLM_CTXT_CTX_ID_MAX) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
/* Set TCM Info */
|
||
|
|
index = 0;
|
||
|
|
page_num = 0;
|
||
|
|
for (i = 0; i < vlm_pgtable->tcm_pgtable.page_num; i++) {
|
||
|
|
index = find_next_bit(vlm_pgtable->tcm_pgtable.table_tcm,
|
||
|
|
TABLE_TCM_MAX, index);
|
||
|
|
//LOG_DEBUG("Find Bit index %lu!!\n", index);
|
||
|
|
g_vlm_pgtable[ctxID].page[i].type = REVISER_MEM_TYPE_TCM;
|
||
|
|
g_vlm_pgtable[ctxID].page[i].dst = index;
|
||
|
|
g_vlm_pgtable[ctxID].page[i].valid = 1;
|
||
|
|
|
||
|
|
index++;
|
||
|
|
page_num++;
|
||
|
|
}
|
||
|
|
/* Save and use when clear TCM*/
|
||
|
|
memcpy(&g_vlm_pgtable[ctxID].tcm, &vlm_pgtable->tcm_pgtable,
|
||
|
|
sizeof(struct table_tcm));
|
||
|
|
|
||
|
|
/* Set Dram Info */
|
||
|
|
for (i = page_num; i < VLM_REMAP_TABLE_MAX; i++) {
|
||
|
|
g_vlm_pgtable[ctxID].page[i].type = REVISER_MEM_TYPE_DRAM;
|
||
|
|
g_vlm_pgtable[ctxID].page[i].dst = i;
|
||
|
|
g_vlm_pgtable[ctxID].page[i].valid = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*sys_page_num = tcm + mmsys(todo) */
|
||
|
|
g_vlm_pgtable[ctxID].sys_page_num = vlm_pgtable->tcm_pgtable.page_num;
|
||
|
|
g_vlm_pgtable[ctxID].page_num = vlm_pgtable->page_num;
|
||
|
|
|
||
|
|
|
||
|
|
LOG_DEBUG("[out] ctx(%lu) sys(%u) pg(%d) tcm_pg(%d) tcm_pgtb(%lx)\n",
|
||
|
|
ctxID,
|
||
|
|
g_vlm_pgtable[ctxID].sys_page_num,
|
||
|
|
g_vlm_pgtable[ctxID].page_num,
|
||
|
|
g_vlm_pgtable[ctxID].tcm.page_num,
|
||
|
|
g_vlm_pgtable[ctxID].tcm.table_tcm[0]
|
||
|
|
);
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
static int _reviser_clear_vlm_pgtable(void *drvinfo,
|
||
|
|
unsigned long ctxID, struct table_tcm *tcm_pgtable)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (ctxID >= VLM_CTXT_CTX_ID_MAX) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (tcm_pgtable == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
/* Return TCM page table for clearing TCM */
|
||
|
|
memcpy(tcm_pgtable, &g_vlm_pgtable[ctxID].tcm,
|
||
|
|
sizeof(struct table_tcm));
|
||
|
|
|
||
|
|
|
||
|
|
memset(&g_vlm_pgtable[ctxID], 0, sizeof(struct vlm_pgtable));
|
||
|
|
|
||
|
|
LOG_DEBUG("ctxid(%lu)\n", ctxID);
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int reviser_table_get_vlm(void *drvinfo,
|
||
|
|
uint32_t requset_size, bool force,
|
||
|
|
unsigned long *id, uint32_t *tcm_size)
|
||
|
|
{
|
||
|
|
//uint32_t page_num;
|
||
|
|
unsigned long ctxid;
|
||
|
|
//struct table_tcm tcm_pgtable;
|
||
|
|
struct table_vlm vlm_pgtable;
|
||
|
|
|
||
|
|
if (requset_size > VLM_SIZE) {
|
||
|
|
LOG_ERR("requset_size(%x) is too larger\n", requset_size);
|
||
|
|
goto fail;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(&vlm_pgtable, 0, sizeof(struct table_vlm));
|
||
|
|
vlm_pgtable.page_num = DIV_ROUND_UP(requset_size, VLM_BANK_SIZE);
|
||
|
|
LOG_DEBUG("[in] requset_size(%x) page_num(%u) force(%d)\n",
|
||
|
|
requset_size, vlm_pgtable.page_num, force);
|
||
|
|
|
||
|
|
if (reviser_table_get_ctxID_sync(drvinfo, &ctxid)) {
|
||
|
|
LOG_ERR("Get CTX ID Fail\n");
|
||
|
|
goto fail;
|
||
|
|
}
|
||
|
|
//LOG_DEBUG("ctxID: %lu\n", ctxid);
|
||
|
|
|
||
|
|
if (VLM_TCM_BANK_MAX == 0) {
|
||
|
|
LOG_DEBUG("Force set to false because TCM is zero\n");
|
||
|
|
force = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (force) {
|
||
|
|
if (reviser_table_get_tcm_sync(drvinfo,
|
||
|
|
vlm_pgtable.page_num,
|
||
|
|
&vlm_pgtable.tcm_pgtable)) {
|
||
|
|
LOG_ERR("Force Get TCM Fail\n");
|
||
|
|
goto free_ctxid;
|
||
|
|
}
|
||
|
|
|
||
|
|
} else {
|
||
|
|
//Get TCM fail , all page to DRAM
|
||
|
|
//To Do List: Fragmentation , may return max available TCM page?
|
||
|
|
if (reviser_table_get_tcm(drvinfo,
|
||
|
|
vlm_pgtable.page_num,
|
||
|
|
&vlm_pgtable.tcm_pgtable)) {
|
||
|
|
LOG_DEBUG("Use Dram ctxid %lu\n", ctxid);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (_reviser_set_vlm_pgtable(drvinfo, ctxid, &vlm_pgtable)) {
|
||
|
|
LOG_ERR("Set VLM Page Table Fail\n");
|
||
|
|
goto free_tcm;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!reviser_power_on(drvinfo)) {
|
||
|
|
/* Set HW remap table */
|
||
|
|
if (reviser_table_set_remap(drvinfo, ctxid)) {
|
||
|
|
LOG_ERR("Set Remap Fail and power off\n");
|
||
|
|
if (reviser_power_off(drvinfo))
|
||
|
|
LOG_ERR("Power OFF Fail\n");
|
||
|
|
|
||
|
|
goto free_vlm;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
LOG_ERR("Power ON Fail\n");
|
||
|
|
goto free_vlm;
|
||
|
|
}
|
||
|
|
|
||
|
|
LOG_DEBUG("[out] vlm page_num(%u) tcm_valid(%lx) ctxid(%lu)\n",
|
||
|
|
vlm_pgtable.tcm_pgtable.page_num,
|
||
|
|
vlm_pgtable.tcm_pgtable.table_tcm[0], ctxid);
|
||
|
|
|
||
|
|
*tcm_size = vlm_pgtable.tcm_pgtable.page_num * VLM_BANK_SIZE;
|
||
|
|
*id = ctxid;
|
||
|
|
|
||
|
|
LOG_DEBUG("[out] CtxID(%lu) page_num(%u)\n",
|
||
|
|
ctxid,
|
||
|
|
vlm_pgtable.tcm_pgtable.page_num);
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
free_vlm:
|
||
|
|
if (_reviser_clear_vlm_pgtable(drvinfo, ctxid,
|
||
|
|
&vlm_pgtable.tcm_pgtable))
|
||
|
|
LOG_ERR("Clear VLM PageTable fail\n");
|
||
|
|
|
||
|
|
free_tcm:
|
||
|
|
if (reviser_table_free_tcm(drvinfo, &vlm_pgtable.tcm_pgtable))
|
||
|
|
LOG_ERR("Free TCM fail\n");
|
||
|
|
|
||
|
|
free_ctxid:
|
||
|
|
if (reviser_table_free_ctxID(drvinfo, ctxid))
|
||
|
|
LOG_ERR("Free ctxID fail\n");
|
||
|
|
|
||
|
|
fail:
|
||
|
|
*id = 0;
|
||
|
|
*tcm_size = 0;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int reviser_table_free_vlm(void *drvinfo, uint32_t ctxid)
|
||
|
|
{
|
||
|
|
struct table_tcm tcm_pgtable;
|
||
|
|
int ret = 0;
|
||
|
|
|
||
|
|
//LOG_DEBUG("free ctxid: %u\n", ctxid);
|
||
|
|
if (ctxid >= VLM_CTXT_CTX_ID_MAX) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
ret = -1;
|
||
|
|
goto power_off;
|
||
|
|
}
|
||
|
|
if (reviser_table_clear_remap(drvinfo, ctxid)) {
|
||
|
|
LOG_ERR("Clear Remap Fail\n");
|
||
|
|
ret = -1;
|
||
|
|
goto power_off;
|
||
|
|
}
|
||
|
|
|
||
|
|
//LOG_DEBUG("reviser_table_clear_remap done %d\n", ctxid);
|
||
|
|
|
||
|
|
memset(&tcm_pgtable, 0, sizeof(struct table_tcm));
|
||
|
|
if (_reviser_clear_vlm_pgtable(drvinfo, ctxid, &tcm_pgtable)) {
|
||
|
|
LOG_ERR("Clear VLM PageTable Fail\n");
|
||
|
|
ret = -1;
|
||
|
|
goto power_off;
|
||
|
|
}
|
||
|
|
|
||
|
|
//LOG_DEBUG("_reviser_clear_vlm_pgtable ctxid(%d)\n", ctxid);
|
||
|
|
|
||
|
|
if (reviser_table_free_tcm(drvinfo, &tcm_pgtable)) {
|
||
|
|
LOG_ERR("Free TCM Fail\n");
|
||
|
|
ret = -1;
|
||
|
|
goto power_off;
|
||
|
|
}
|
||
|
|
//LOG_DEBUG("reviser_table_free_tcm ctxid(%d) page_num(%u)\n",
|
||
|
|
// ctxid, tcm_pgtable.page_num);
|
||
|
|
|
||
|
|
if (reviser_table_free_ctxID(drvinfo, ctxid)) {
|
||
|
|
LOG_ERR("Free ctxID Fail\n");
|
||
|
|
ret = -1;
|
||
|
|
goto power_off;
|
||
|
|
}
|
||
|
|
LOG_DEBUG("ctxid(%u) page_num(%u)\n",
|
||
|
|
ctxid, tcm_pgtable.page_num);
|
||
|
|
|
||
|
|
power_off:
|
||
|
|
if (reviser_power_off(drvinfo)) {
|
||
|
|
LOG_ERR("Power OFF Fail\n");
|
||
|
|
ret = -1;
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int reviser_table_init_remap(void *drvinfo)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_remap);
|
||
|
|
memset(&g_table_remap, 0, sizeof(struct table_remap));
|
||
|
|
mutex_unlock(&reviser_device->mutex_remap);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
int reviser_table_set_remap(void *drvinfo, unsigned long ctxid)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
uint32_t setbits;
|
||
|
|
unsigned long index = 0;
|
||
|
|
uint32_t i;
|
||
|
|
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_remap);
|
||
|
|
mutex_lock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
setbits = bitmap_weight(g_table_remap.valid, VLM_REMAP_TABLE_MAX);
|
||
|
|
//LOG_DEBUG(" setbits [%d]\n", setbits);
|
||
|
|
|
||
|
|
if (VLM_REMAP_TABLE_MAX - setbits < g_vlm_pgtable[ctxid].sys_page_num) {
|
||
|
|
|
||
|
|
LOG_ERR("Remap Zero bits (%d) > vlm[%lu] page[%d]\n",
|
||
|
|
VLM_REMAP_TABLE_MAX - setbits,
|
||
|
|
ctxid, g_vlm_pgtable[ctxid].sys_page_num);
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
|
||
|
|
index = 0;
|
||
|
|
for (i = 0; i < g_vlm_pgtable[ctxid].sys_page_num; i++) {
|
||
|
|
index = find_next_zero_bit(g_table_remap.valid,
|
||
|
|
VLM_REMAP_TABLE_MAX, index);
|
||
|
|
//LOG_DEBUG("Find Zero Bit index %lu!!\n", index);
|
||
|
|
if (index == VLM_REMAP_TABLE_MAX) {
|
||
|
|
LOG_ERR("CanNot Find Zero Bit!!\n");
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
|
||
|
|
g_table_remap.table_remap_mem[index].ctxid = ctxid;
|
||
|
|
g_table_remap.table_remap_mem[index].src = i;
|
||
|
|
g_table_remap.table_remap_mem[index].dst =
|
||
|
|
g_vlm_pgtable[ctxid].page[i].dst;
|
||
|
|
//Set to page table for clear VLM
|
||
|
|
g_vlm_pgtable[ctxid].page[i].vlm = index;
|
||
|
|
|
||
|
|
bitmap_set(g_table_remap.valid, index, 1);
|
||
|
|
/* Set HW remap table */
|
||
|
|
if (reviser_set_remap_table(drvinfo, index, 1,
|
||
|
|
ctxid, i, g_vlm_pgtable[ctxid].page[i].dst)) {
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
/* DEBUG and force set remap to specific value*/
|
||
|
|
_reviser_force_remap(drvinfo);
|
||
|
|
//setbits = bitmap_weight(g_table_remap.valid, VLM_REMAP_TABLE_MAX);
|
||
|
|
//LOG_DEBUG("Done setbits [%d]\n", setbits);
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
mutex_unlock(&reviser_device->mutex_remap);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
free_mutex:
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
mutex_unlock(&reviser_device->mutex_remap);
|
||
|
|
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
int reviser_table_clear_remap(void *drvinfo, unsigned long ctxid)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
uint32_t setbits;
|
||
|
|
unsigned long index = 0;
|
||
|
|
uint32_t i;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (ctxid >= VLM_CTXT_CTX_ID_MAX) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_remap);
|
||
|
|
mutex_lock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
setbits = bitmap_weight(g_table_remap.valid, VLM_REMAP_TABLE_MAX);
|
||
|
|
//LOG_DEBUG(" setbits [%d]\n", setbits);
|
||
|
|
if (setbits < g_vlm_pgtable[ctxid].sys_page_num) {
|
||
|
|
|
||
|
|
LOG_ERR("Remap (%u)[%lu][%u]\n",
|
||
|
|
setbits, ctxid,
|
||
|
|
g_vlm_pgtable[ctxid].sys_page_num);
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
|
||
|
|
index = 0;
|
||
|
|
for (i = 0; i < g_vlm_pgtable[ctxid].sys_page_num; i++) {
|
||
|
|
index = g_vlm_pgtable[ctxid].page[i].vlm;
|
||
|
|
|
||
|
|
bitmap_clear(g_table_remap.valid, index, 1);
|
||
|
|
|
||
|
|
if (reviser_set_remap_table(drvinfo,
|
||
|
|
index, 0, ctxid, index, index))
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
/* DEBUG and force set remap to specific value*/
|
||
|
|
_reviser_force_remap(drvinfo);
|
||
|
|
|
||
|
|
LOG_DEBUG("ctxid [%lu]\n", ctxid);
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
mutex_unlock(&reviser_device->mutex_remap);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
free_mutex:
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
mutex_unlock(&reviser_device->mutex_remap);
|
||
|
|
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
void reviser_table_print_vlm(void *drvinfo, uint32_t ctxid, void *s_file)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
uint32_t i;
|
||
|
|
struct seq_file *s = (struct seq_file *)s_file;
|
||
|
|
char strtype[8];
|
||
|
|
int count = 0;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (ctxid >= VLM_REMAP_TABLE_MAX) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
mutex_lock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
LOG_CON(s, "=============================\n");
|
||
|
|
LOG_CON(s, " vlm [%d] page_num[%d]\n",
|
||
|
|
ctxid, g_vlm_pgtable[ctxid].page_num);
|
||
|
|
|
||
|
|
LOG_CON(s, "-----------------------------\n");
|
||
|
|
for (i = 0; i < VLM_REMAP_TABLE_MAX; i++) {
|
||
|
|
switch (g_vlm_pgtable[ctxid].page[i].type) {
|
||
|
|
case REVISER_MEM_TYPE_TCM:
|
||
|
|
count = snprintf(strtype, sizeof(strtype), "TCM");
|
||
|
|
break;
|
||
|
|
case REVISER_MEM_TYPE_DRAM:
|
||
|
|
count = snprintf(strtype, sizeof(strtype), "DRAM");
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
count = snprintf(strtype, sizeof(strtype), "NONE");
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (count > 0)
|
||
|
|
LOG_CON(s, "v[%d] src[%02d] dst[%02d] vlm[%02d] type[%s]\n",
|
||
|
|
g_vlm_pgtable[ctxid].page[i].valid, i,
|
||
|
|
g_vlm_pgtable[ctxid].page[i].dst,
|
||
|
|
g_vlm_pgtable[ctxid].page[i].vlm, strtype);
|
||
|
|
}
|
||
|
|
LOG_CON(s, "=============================\n");
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
}
|
||
|
|
|
||
|
|
int reviser_table_swapout_vlm(void *drvinfo, unsigned long ctxid)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
void *buffer;
|
||
|
|
size_t size;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (ctxid >= VLM_CTXT_CTX_ID_MAX) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
// if there is tcm then swap
|
||
|
|
if (g_vlm_pgtable[ctxid].tcm.page_num > 0) {
|
||
|
|
size = VLM_BANK_SIZE * g_vlm_pgtable[ctxid].tcm.page_num;
|
||
|
|
buffer = (void *) __get_free_pages(GFP_KERNEL, get_order(size));
|
||
|
|
if (buffer == NULL) {
|
||
|
|
LOG_ERR("failed to allocate 0x%lx buffer.\n", size);
|
||
|
|
goto free_mutex;
|
||
|
|
}
|
||
|
|
|
||
|
|
memcpy_fromio(buffer, reviser_device->tcm_base, size);
|
||
|
|
g_vlm_pgtable[ctxid].swap_addr = (uint64_t) buffer;
|
||
|
|
|
||
|
|
LOG_DEBUG("Copy to kva %p\n", buffer);
|
||
|
|
LOG_DEBUG("Copy to g_vlm_pgtable[%lu].swap_addr %llx\n",
|
||
|
|
ctxid, g_vlm_pgtable[ctxid].swap_addr);
|
||
|
|
} else {
|
||
|
|
LOG_DEBUG("No TCM!\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
free_mutex:
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
}
|
||
|
|
int reviser_table_swapin_vlm(void *drvinfo, unsigned long ctxid)
|
||
|
|
{
|
||
|
|
struct reviser_dev_info *reviser_device = NULL;
|
||
|
|
void *buffer;
|
||
|
|
size_t size;
|
||
|
|
|
||
|
|
DEBUG_TAG;
|
||
|
|
|
||
|
|
if (ctxid >= VLM_CTXT_CTX_ID_MAX) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (drvinfo == NULL) {
|
||
|
|
LOG_ERR("invalid argument\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
reviser_device = (struct reviser_dev_info *)drvinfo;
|
||
|
|
|
||
|
|
mutex_lock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
|
||
|
|
// if there is tcm then swap
|
||
|
|
if (g_vlm_pgtable[ctxid].tcm.page_num > 0) {
|
||
|
|
|
||
|
|
buffer = (void *) g_vlm_pgtable[ctxid].swap_addr;
|
||
|
|
size = g_vlm_pgtable[ctxid].tcm.page_num * VLM_BANK_SIZE;
|
||
|
|
memcpy_toio(reviser_device->tcm_base, buffer, size);
|
||
|
|
|
||
|
|
g_vlm_pgtable[ctxid].swap_addr = 0;
|
||
|
|
free_pages((unsigned long)buffer, get_order(size));
|
||
|
|
|
||
|
|
LOG_DEBUG("Restore kva %p to context %lu\n2", buffer, ctxid);
|
||
|
|
} else {
|
||
|
|
LOG_DEBUG("No TCM!\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
mutex_unlock(&reviser_device->mutex_vlm_pgtable);
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}
|