buffer->mx = mx;
miframman = scsc_mx_get_ramman(mx);
- mem = miframman_alloc(miframman, num_packets * packet_size, 4);
+ mem = miframman_alloc(miframman, num_packets * packet_size, 4, MIFRAMMAN_OWNER_COMMON);
if (!mem)
return -ENOMEM;
- ridx = miframman_alloc(miframman, sizeof(uint32_t), 4);
+ ridx = miframman_alloc(miframman, sizeof(uint32_t), 4, MIFRAMMAN_OWNER_COMMON);
if (!ridx) {
miframman_free(miframman, mem);
return -ENOMEM;
}
- widx = miframman_alloc(miframman, sizeof(uint32_t), 4);
+ widx = miframman_alloc(miframman, sizeof(uint32_t), 4, MIFRAMMAN_OWNER_COMMON);
if (!widx) {
miframman_free(miframman, ridx);
miframman_free(miframman, mem);
MIF_PROCFS_RW_FILE_OPS(mif_dump);
MIF_PROCFS_RW_FILE_OPS(mif_writemem);
MIF_PROCFS_RW_FILE_OPS(mif_reg);
-/*
-MIF_PROCFS_SEQ_FILE_OPS(mif_dbg);
-*/
/* miframman ops */
MIF_PROCFS_RO_FILE_OPS(ramman_total);
MIF_PROCFS_RO_FILE_OPS(ramman_used);
MIF_PROCFS_RO_FILE_OPS(ramman_size);
+MIF_PROCFS_SEQ_FILE_OPS(ramman_list);
+
static ssize_t mifprocfs_mif_reg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos)
{
char buf[128];
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
+/* List allocations per ramman */
+static int mifprocfs_ramman_list_show(struct seq_file *m, void *v)
+{
+ struct miframman *ramman = (struct miframman *)m->private;
+ (void)v;
+
+ miframman_log(ramman, m);
+
+ return 0;
+}
+
static const char *procdir = "driver/mif_ctrl";
static int refcount;
MIF_PROCFS_ADD_FILE(NULL, mif_writemem, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MIF_PROCFS_ADD_FILE(NULL, mif_dump, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MIF_PROCFS_ADD_FILE(NULL, mif_reg, parent, S_IRUSR | S_IRGRP);
- /*
- MIF_PROCFS_SEQ_ADD_FILE(NULL, mif_dbg, parent, S_IRUSR | S_IRGRP | S_IROTH);
- */
} else {
SCSC_TAG_INFO(MIF, "failed to create /proc dir\n");
return -EINVAL;
MIF_PROCFS_REMOVE_FILE(mif_writemem, procfs_dir);
MIF_PROCFS_REMOVE_FILE(mif_dump, procfs_dir);
MIF_PROCFS_REMOVE_FILE(mif_reg, procfs_dir);
- /*
- MIF_PROCFS_REMOVE_FILE(mif_dbg, procfs_dir);
- */
/* De-ref the root dir */
destroy_procfs_dir();
MIF_PROCFS_ADD_FILE(ramman, ramman_free, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MIF_PROCFS_ADD_FILE(ramman, ramman_used, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ MIF_PROCFS_SEQ_ADD_FILE(ramman, ramman_list, parent, S_IRUSR | S_IRGRP | S_IROTH);
+
procfs_dir_ramman[ramman_instance] = parent;
proc_miframman[ramman_instance] = ramman;
MIF_PROCFS_REMOVE_FILE(ramman_free, procfs_dir_ramman[ramman_instance]);
MIF_PROCFS_REMOVE_FILE(ramman_used, procfs_dir_ramman[ramman_instance]);
+ MIF_PROCFS_REMOVE_FILE(ramman_list, procfs_dir_ramman[ramman_instance]);
+
(void)snprintf(dir, sizeof(dir), "%s%d", ramman_procdir, ramman_instance);
remove_proc_entry(dir, procfs_dir);
procfs_dir_ramman[ramman_instance] = NULL;
struct proc_dir_entry *entry; \
entry = proc_create_data(# name, mode, parent, &mifprocfs_ ## name ## _fops, _sdev); \
if (!entry) { \
- goto err; \
+ break; \
} \
MIF_PROCFS_SET_UID_GID(entry); \
} while (0)
mifabox->aboxram = (struct scsc_bt_audio_abox *)start_aboxram;
}
-void *__miframman_alloc(struct miframman *ram, size_t nbytes)
+void *__miframman_alloc(struct miframman *ram, size_t nbytes, int tag)
{
unsigned int index = 0;
unsigned int available;
free_mem = ram->start_dram +
MIFRAMMAN_BLOCK_SIZE * index;
- /* Mark the blocks as used */
- ram->bitmap[index++] = BLOCK_BOUND;
- for (i = 1; i < num_blocks; i++)
- ram->bitmap[index++] = BLOCK_INUSE;
+ /* Mark the block boundary as used */
+ ram->bitmap[index] = BLOCK_BOUND;
+ ram->bitmap[index] |= (u8)(tag << MIFRAMMAN_BLOCK_OWNER_SHIFT); /* Add owner tack for tracking */
+ index++;
+
+ /* Additional blocks in this allocation */
+ for (i = 1; i < num_blocks; i++) {
+ ram->bitmap[index] = BLOCK_INUSE;
+ ram->bitmap[index] |= (u8)(tag << MIFRAMMAN_BLOCK_OWNER_SHIFT); /* Add owner tack for tracking */
+ index++;
+ }
ram->free_mem -= num_blocks * MIFRAMMAN_BLOCK_SIZE;
goto exit;
(*(((void **)((uintptr_t)(mem) & \
(~(uintptr_t)(sizeof(void *) - 1)))) - 1))
-void *miframman_alloc(struct miframman *ram, size_t nbytes, size_t align)
+/*
+ * Allocate shared DRAM block
+ *
+ * Parameters:
+ * ram - pool identifier
+ * nbytes - allocation size
+ * align - allocation alignment
+ * tag - owner identifier (typically service ID), 4 bits.
+ *
+ * Returns
+ * Pointer to allocated area, or NULL
+ */
+void *miframman_alloc(struct miframman *ram, size_t nbytes, size_t align, int tag)
{
void *mem, *align_mem = NULL;
if (align < sizeof(void *))
align = sizeof(void *);
- mem = __miframman_alloc(ram, nbytes + align + sizeof(void *));
+ mem = __miframman_alloc(ram, nbytes + align + sizeof(void *), tag);
if (!mem)
goto end;
return align_mem;
}
+/*
+ * Free shared DRAM block
+ *
+ * Parameters:
+ * ram - pool identifier
+ * mem - buffer to free
+ */
void __miframman_free(struct miframman *ram, void *mem)
{
unsigned int index, num_blocks = 0;
}
/* Check it is a Boundary block */
- if (ram->bitmap[index] != BLOCK_BOUND) {
+ if ((ram->bitmap[index] & MIFRAMMAN_BLOCK_STATUS_MASK) != BLOCK_BOUND) {
SCSC_TAG_ERR(MIF, "Incorrect Block descriptor\n");
return;
}
-
ram->bitmap[index++] = BLOCK_FREE;
+
+ /* Free remaining blocks */
num_blocks++;
- while (index < ram->num_blocks && ram->bitmap[index] == BLOCK_INUSE) {
+ while (index < ram->num_blocks && (ram->bitmap[index] & MIFRAMMAN_BLOCK_STATUS_MASK) == BLOCK_INUSE) {
ram->bitmap[index++] = BLOCK_FREE;
num_blocks++;
}
/* Caller should provide locking */
void miframman_deinit(struct miframman *ram)
{
- /* Mark all the blocks as INUSE to prevent new allocations */
+ /* Mark all the blocks as INUSE (by Common) to prevent new allocations */
memset(ram->bitmap, BLOCK_INUSE, sizeof(ram->bitmap));
ram->num_blocks = 0;
mifabox->aboxram = NULL;
}
+/* Log current allocations in a ramman in proc */
+void miframman_log(struct miframman *ram, struct seq_file *fd)
+{
+ unsigned int b;
+ unsigned int i;
+ int tag;
+ size_t num_blocks = 0;
+
+ if (!ram)
+ return;
+
+ seq_printf(fd, "ramman: start_dram %p, size %zd, free_mem %u\n\n",
+ ram->start_region, ram->size_pool, ram->free_mem);
+
+ for (b = 0; b < ram->num_blocks; b++) {
+ if ((ram->bitmap[b] & MIFRAMMAN_BLOCK_STATUS_MASK) == BLOCK_BOUND) {
+ /* Found a boundary allocation */
+ num_blocks++;
+ tag = (ram->bitmap[b] & MIFRAMMAN_BLOCK_OWNER_MASK) >> MIFRAMMAN_BLOCK_OWNER_SHIFT;
+
+ /* Count subsequent blocks in this group */
+ for (i = 1;
+ i < ram->num_blocks && (ram->bitmap[b + i] & MIFRAMMAN_BLOCK_STATUS_MASK) == BLOCK_INUSE;
+ i++) {
+ /* Check owner matches boundary block */
+ int newtag = (ram->bitmap[b + i] & MIFRAMMAN_BLOCK_OWNER_MASK) >> MIFRAMMAN_BLOCK_OWNER_SHIFT;
+ if (newtag != tag) {
+ seq_printf(fd, "Allocated block tag %d doesn't match boundary tag %d, index %d, %p\n",
+ newtag, tag, b + i,
+ ram->start_dram + (b + i) * MIFRAMMAN_BLOCK_SIZE);
+ }
+ num_blocks++;
+ }
+ seq_printf(fd, "index %8d, svc %d, bytes %12d, blocks %10d, %p\n",
+ b, tag,
+ (i * MIFRAMMAN_BLOCK_SIZE),
+ i,
+ ram->start_dram + (b * MIFRAMMAN_BLOCK_SIZE));
+ }
+ }
+}
void miframman_init(struct miframman *ram, void *start_dram, size_t size_pool, void *start_region);
void miframabox_init(struct mifabox *mifabox, void *start_aboxram);
-void *miframman_alloc(struct miframman *ram, size_t nbytes, size_t align);
+void *miframman_alloc(struct miframman *ram, size_t nbytes, size_t align, int tag);
void miframman_free(struct miframman *ram, void *mem);
void miframman_deinit(struct miframman *ram);
void miframabox_deinit(struct mifabox *mifabox);
+void miframman_log(struct miframman *ram, struct seq_file *fd);
#define MIFRAMMAN_MAXMEM (16 * 1024 * 1024)
#define MIFRAMMAN_BLOCK_SIZE (64)
#define MIFRAMMAN_NUM_BLOCKS ((MIFRAMMAN_MAXMEM) / (MIFRAMMAN_BLOCK_SIZE))
+/* Block status in lower nibble */
+#define MIFRAMMAN_BLOCK_STATUS_MASK 0x0f
#define BLOCK_FREE 0
#define BLOCK_INUSE 1
-#define BLOCK_BOUND 2
+#define BLOCK_BOUND 2 /* Block allocation boundary */
+
+/* Block owner in upper nibble */
+#define MIFRAMMAN_BLOCK_OWNER_MASK 0xf0
+#define MIFRAMMAN_BLOCK_OWNER_SHIFT 4
+
+#define MIFRAMMAN_OWNER_COMMON 0 /* Owner tag for Common driver */
/* Inclusion in core.c treat it as opaque */
struct miframman {
}
-/* Lock should be adquired by caller */
+/* Lock should be acquired by caller */
int mxlogger_init(struct scsc_mx *mx, struct mxlogger *mxlogger, uint32_t mem_sz)
{
struct miframman *miframman;
miframman = scsc_mx_get_ramman2(mx);
if (!miframman)
return -ENOMEM;
- mxlogger->mem = miframman_alloc(miframman, mem_sz, 32);
+ mxlogger->mem = miframman_alloc(miframman, mem_sz, 32, MIFRAMMAN_OWNER_COMMON);
if (!mxlogger->mem) {
SCSC_TAG_ERR(MXMAN, "Error allocating memory for MXLOGGER\n");
return -ENOMEM;
* Allocate & Initialise Infrastructre Config Structure
* including the mx management stack config information.
*/
- mxconf = miframman_alloc(scsc_mx_get_ramman(mx), sizeof(struct mxconf), 4);
+ mxconf = miframman_alloc(scsc_mx_get_ramman(mx), sizeof(struct mxconf), 4, MIFRAMMAN_OWNER_COMMON);
if (!mxconf) {
SCSC_TAG_ERR(MXMAN, "miframman_alloc() failed\n");
gdb_transport_release(scsc_mx_get_gdb_transport_m4(mx));
return -ENOMEM;
}
- mem = miframman_alloc(ramman, nbytes, align);
+ mem = miframman_alloc(ramman, nbytes, align, service->id);
if (!mem) {
SCSC_TAG_ERR(MXMAN, "miframman_alloc() failed\n");
*ref = SCSC_MIFRAM_INVALID_REF;