habanalabs: move driver to accel subsystem
[linux-2.6-microblaze.git] / drivers / misc / habanalabs / common / state_dump.c
diff --git a/drivers/misc/habanalabs/common/state_dump.c b/drivers/misc/habanalabs/common/state_dump.c
deleted file mode 100644 (file)
index 3a9931f..0000000
+++ /dev/null
@@ -1,718 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-/*
- * Copyright 2021 HabanaLabs, Ltd.
- * All Rights Reserved.
- */
-
-#include <linux/vmalloc.h>
-#include <uapi/drm/habanalabs_accel.h>
-#include "habanalabs.h"
-
-/**
- * hl_format_as_binary - helper function, format an integer as binary
- *                       using supplied scratch buffer
- * @buf: the buffer to use
- * @buf_len: buffer capacity
- * @n: number to format
- *
- * Returns pointer to buffer
- */
-char *hl_format_as_binary(char *buf, size_t buf_len, u32 n)
-{
-       int i;
-       u32 bit;
-       bool leading0 = true;
-       char *wrptr = buf;
-
-       if (buf_len > 0 && buf_len < 3) {
-               *wrptr = '\0';
-               return buf;
-       }
-
-       wrptr[0] = '0';
-       wrptr[1] = 'b';
-       wrptr += 2;
-       /* Remove 3 characters from length for '0b' and '\0' termination */
-       buf_len -= 3;
-
-       for (i = 0; i < sizeof(n) * BITS_PER_BYTE && buf_len; ++i, n <<= 1) {
-               /* Writing bit calculation in one line would cause a false
-                * positive static code analysis error, so splitting.
-                */
-               bit = n & (1 << (sizeof(n) * BITS_PER_BYTE - 1));
-               bit = !!bit;
-               leading0 &= !bit;
-               if (!leading0) {
-                       *wrptr = '0' + bit;
-                       ++wrptr;
-               }
-       }
-
-       *wrptr = '\0';
-
-       return buf;
-}
-
-/**
- * resize_to_fit - helper function, resize buffer to fit given amount of data
- * @buf: destination buffer double pointer
- * @size: pointer to the size container
- * @desired_size: size the buffer must contain
- *
- * Returns 0 on success or error code on failure.
- * On success, the size of buffer is at least desired_size. Buffer is allocated
- * via vmalloc and must be freed with vfree.
- */
-static int resize_to_fit(char **buf, size_t *size, size_t desired_size)
-{
-       char *resized_buf;
-       size_t new_size;
-
-       if (*size >= desired_size)
-               return 0;
-
-       /* Not enough space to print all, have to resize */
-       new_size = max_t(size_t, PAGE_SIZE, round_up(desired_size, PAGE_SIZE));
-       resized_buf = vmalloc(new_size);
-       if (!resized_buf)
-               return -ENOMEM;
-       memcpy(resized_buf, *buf, *size);
-       vfree(*buf);
-       *buf = resized_buf;
-       *size = new_size;
-
-       return 1;
-}
-
-/**
- * hl_snprintf_resize() - print formatted data to buffer, resize as needed
- * @buf: buffer double pointer, to be written to and resized, must be either
- *       NULL or allocated with vmalloc.
- * @size: current size of the buffer
- * @offset: current offset to write to
- * @format: format of the data
- *
- * This function will write formatted data into the buffer. If buffer is not
- * large enough, it will be resized using vmalloc. Size may be modified if the
- * buffer was resized, offset will be advanced by the number of bytes written
- * not including the terminating character
- *
- * Returns 0 on success or error code on failure
- *
- * Note that the buffer has to be manually released using vfree.
- */
-int hl_snprintf_resize(char **buf, size_t *size, size_t *offset,
-                          const char *format, ...)
-{
-       va_list args;
-       size_t length;
-       int rc;
-
-       if (*buf == NULL && (*size != 0 || *offset != 0))
-               return -EINVAL;
-
-       va_start(args, format);
-       length = vsnprintf(*buf + *offset, *size - *offset, format, args);
-       va_end(args);
-
-       rc = resize_to_fit(buf, size, *offset + length + 1);
-       if (rc < 0)
-               return rc;
-       else if (rc > 0) {
-               /* Resize was needed, write again */
-               va_start(args, format);
-               length = vsnprintf(*buf + *offset, *size - *offset, format,
-                                  args);
-               va_end(args);
-       }
-
-       *offset += length;
-
-       return 0;
-}
-
-/**
- * hl_sync_engine_to_string - convert engine type enum to string literal
- * @engine_type: engine type (TPC/MME/DMA)
- *
- * Return the resolved string literal
- */
-const char *hl_sync_engine_to_string(enum hl_sync_engine_type engine_type)
-{
-       switch (engine_type) {
-       case ENGINE_DMA:
-               return "DMA";
-       case ENGINE_MME:
-               return "MME";
-       case ENGINE_TPC:
-               return "TPC";
-       }
-       return "Invalid Engine Type";
-}
-
-/**
- * hl_print_resize_sync_engine - helper function, format engine name and ID
- * using hl_snprintf_resize
- * @buf: destination buffer double pointer to be used with hl_snprintf_resize
- * @size: pointer to the size container
- * @offset: pointer to the offset container
- * @engine_type: engine type (TPC/MME/DMA)
- * @engine_id: engine numerical id
- *
- * Returns 0 on success or error code on failure
- */
-static int hl_print_resize_sync_engine(char **buf, size_t *size, size_t *offset,
-                               enum hl_sync_engine_type engine_type,
-                               u32 engine_id)
-{
-       return hl_snprintf_resize(buf, size, offset, "%s%u",
-                       hl_sync_engine_to_string(engine_type), engine_id);
-}
-
-/**
- * hl_state_dump_get_sync_name - transform sync object id to name if available
- * @hdev: pointer to the device
- * @sync_id: sync object id
- *
- * Returns a name literal or NULL if not resolved.
- * Note: returning NULL shall not be considered as a failure, as not all
- * sync objects are named.
- */
-const char *hl_state_dump_get_sync_name(struct hl_device *hdev, u32 sync_id)
-{
-       struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
-       struct hl_hw_obj_name_entry *entry;
-
-       hash_for_each_possible(sds->so_id_to_str_tb, entry,
-                               node, sync_id)
-               if (sync_id == entry->id)
-                       return entry->name;
-
-       return NULL;
-}
-
-/**
- * hl_state_dump_get_monitor_name - transform monitor object dump to monitor
- * name if available
- * @hdev: pointer to the device
- * @mon: monitor state dump
- *
- * Returns a name literal or NULL if not resolved.
- * Note: returning NULL shall not be considered as a failure, as not all
- * monitors are named.
- */
-const char *hl_state_dump_get_monitor_name(struct hl_device *hdev,
-                                       struct hl_mon_state_dump *mon)
-{
-       struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
-       struct hl_hw_obj_name_entry *entry;
-
-       hash_for_each_possible(sds->monitor_id_to_str_tb,
-                               entry, node, mon->id)
-               if (mon->id == entry->id)
-                       return entry->name;
-
-       return NULL;
-}
-
-/**
- * hl_state_dump_free_sync_to_engine_map - free sync object to engine map
- * @map: sync object to engine map
- *
- * Note: generic free implementation, the allocation is implemented per ASIC.
- */
-void hl_state_dump_free_sync_to_engine_map(struct hl_sync_to_engine_map *map)
-{
-       struct hl_sync_to_engine_map_entry *entry;
-       struct hlist_node *tmp_node;
-       int i;
-
-       hash_for_each_safe(map->tb, i, tmp_node, entry, node) {
-               hash_del(&entry->node);
-               kfree(entry);
-       }
-}
-
-/**
- * hl_state_dump_get_sync_to_engine - transform sync_id to
- * hl_sync_to_engine_map_entry if available for current id
- * @map: sync object to engine map
- * @sync_id: sync object id
- *
- * Returns the translation entry if found or NULL if not.
- * Note, returned NULL shall not be considered as a failure as the map
- * does not cover all possible, it is a best effort sync ids.
- */
-static struct hl_sync_to_engine_map_entry *
-hl_state_dump_get_sync_to_engine(struct hl_sync_to_engine_map *map, u32 sync_id)
-{
-       struct hl_sync_to_engine_map_entry *entry;
-
-       hash_for_each_possible(map->tb, entry, node, sync_id)
-               if (entry->sync_id == sync_id)
-                       return entry;
-       return NULL;
-}
-
-/**
- * hl_state_dump_read_sync_objects - read sync objects array
- * @hdev: pointer to the device
- * @index: sync manager block index starting with E_N
- *
- * Returns array of size SP_SYNC_OBJ_AMOUNT on success or NULL on failure
- */
-static u32 *hl_state_dump_read_sync_objects(struct hl_device *hdev, u32 index)
-{
-       struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
-       u32 *sync_objects;
-       s64 base_addr; /* Base addr can be negative */
-       int i;
-
-       base_addr = sds->props[SP_SYNC_OBJ_BASE_ADDR] +
-                       sds->props[SP_NEXT_SYNC_OBJ_ADDR] * index;
-
-       sync_objects = vmalloc(sds->props[SP_SYNC_OBJ_AMOUNT] * sizeof(u32));
-       if (!sync_objects)
-               return NULL;
-
-       for (i = 0; i < sds->props[SP_SYNC_OBJ_AMOUNT]; ++i)
-               sync_objects[i] = RREG32(base_addr + i * sizeof(u32));
-
-       return sync_objects;
-}
-
-/**
- * hl_state_dump_free_sync_objects - free sync objects array allocated by
- * hl_state_dump_read_sync_objects
- * @sync_objects: sync objects array
- */
-static void hl_state_dump_free_sync_objects(u32 *sync_objects)
-{
-       vfree(sync_objects);
-}
-
-
-/**
- * hl_state_dump_print_syncs_single_block - print active sync objects on a
- * single block
- * @hdev: pointer to the device
- * @index: sync manager block index starting with E_N
- * @buf: destination buffer double pointer to be used with hl_snprintf_resize
- * @size: pointer to the size container
- * @offset: pointer to the offset container
- * @map: sync engines names map
- *
- * Returns 0 on success or error code on failure
- */
-static int
-hl_state_dump_print_syncs_single_block(struct hl_device *hdev, u32 index,
-                               char **buf, size_t *size, size_t *offset,
-                               struct hl_sync_to_engine_map *map)
-{
-       struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
-       const char *sync_name;
-       u32 *sync_objects = NULL;
-       int rc = 0, i;
-
-       if (sds->sync_namager_names) {
-               rc = hl_snprintf_resize(
-                       buf, size, offset, "%s\n",
-                       sds->sync_namager_names[index]);
-               if (rc)
-                       goto out;
-       }
-
-       sync_objects = hl_state_dump_read_sync_objects(hdev, index);
-       if (!sync_objects) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       for (i = 0; i < sds->props[SP_SYNC_OBJ_AMOUNT]; ++i) {
-               struct hl_sync_to_engine_map_entry *entry;
-               u64 sync_object_addr;
-
-               if (!sync_objects[i])
-                       continue;
-
-               sync_object_addr = sds->props[SP_SYNC_OBJ_BASE_ADDR] +
-                               sds->props[SP_NEXT_SYNC_OBJ_ADDR] * index +
-                               i * sizeof(u32);
-
-               rc = hl_snprintf_resize(buf, size, offset, "sync id: %u", i);
-               if (rc)
-                       goto free_sync_objects;
-               sync_name = hl_state_dump_get_sync_name(hdev, i);
-               if (sync_name) {
-                       rc = hl_snprintf_resize(buf, size, offset, " %s",
-                                               sync_name);
-                       if (rc)
-                               goto free_sync_objects;
-               }
-               rc = hl_snprintf_resize(buf, size, offset, ", value: %u",
-                                       sync_objects[i]);
-               if (rc)
-                       goto free_sync_objects;
-
-               /* Append engine string */
-               entry = hl_state_dump_get_sync_to_engine(map,
-                       (u32)sync_object_addr);
-               if (entry) {
-                       rc = hl_snprintf_resize(buf, size, offset,
-                                               ", Engine: ");
-                       if (rc)
-                               goto free_sync_objects;
-                       rc = hl_print_resize_sync_engine(buf, size, offset,
-                                               entry->engine_type,
-                                               entry->engine_id);
-                       if (rc)
-                               goto free_sync_objects;
-               }
-
-               rc = hl_snprintf_resize(buf, size, offset, "\n");
-               if (rc)
-                       goto free_sync_objects;
-       }
-
-free_sync_objects:
-       hl_state_dump_free_sync_objects(sync_objects);
-out:
-       return rc;
-}
-
-/**
- * hl_state_dump_print_syncs - print active sync objects
- * @hdev: pointer to the device
- * @buf: destination buffer double pointer to be used with hl_snprintf_resize
- * @size: pointer to the size container
- * @offset: pointer to the offset container
- *
- * Returns 0 on success or error code on failure
- */
-static int hl_state_dump_print_syncs(struct hl_device *hdev,
-                                       char **buf, size_t *size,
-                                       size_t *offset)
-
-{
-       struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
-       struct hl_sync_to_engine_map *map;
-       u32 index;
-       int rc = 0;
-
-       map = kzalloc(sizeof(*map), GFP_KERNEL);
-       if (!map)
-               return -ENOMEM;
-
-       rc = sds->funcs.gen_sync_to_engine_map(hdev, map);
-       if (rc)
-               goto free_map_mem;
-
-       rc = hl_snprintf_resize(buf, size, offset, "Non zero sync objects:\n");
-       if (rc)
-               goto out;
-
-       if (sds->sync_namager_names) {
-               for (index = 0; sds->sync_namager_names[index]; ++index) {
-                       rc = hl_state_dump_print_syncs_single_block(
-                               hdev, index, buf, size, offset, map);
-                       if (rc)
-                               goto out;
-               }
-       } else {
-               for (index = 0; index < sds->props[SP_NUM_CORES]; ++index) {
-                       rc = hl_state_dump_print_syncs_single_block(
-                               hdev, index, buf, size, offset, map);
-                       if (rc)
-                               goto out;
-               }
-       }
-
-out:
-       hl_state_dump_free_sync_to_engine_map(map);
-free_map_mem:
-       kfree(map);
-
-       return rc;
-}
-
-/**
- * hl_state_dump_alloc_read_sm_block_monitors - read monitors for a specific
- * block
- * @hdev: pointer to the device
- * @index: sync manager block index starting with E_N
- *
- * Returns an array of monitor data of size SP_MONITORS_AMOUNT or NULL
- * on error
- */
-static struct hl_mon_state_dump *
-hl_state_dump_alloc_read_sm_block_monitors(struct hl_device *hdev, u32 index)
-{
-       struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
-       struct hl_mon_state_dump *monitors;
-       s64 base_addr; /* Base addr can be negative */
-       int i;
-
-       monitors = vmalloc(sds->props[SP_MONITORS_AMOUNT] *
-                          sizeof(struct hl_mon_state_dump));
-       if (!monitors)
-               return NULL;
-
-       base_addr = sds->props[SP_NEXT_SYNC_OBJ_ADDR] * index;
-
-       for (i = 0; i < sds->props[SP_MONITORS_AMOUNT]; ++i) {
-               monitors[i].id = i;
-               monitors[i].wr_addr_low =
-                       RREG32(base_addr + sds->props[SP_MON_OBJ_WR_ADDR_LOW] +
-                               i * sizeof(u32));
-
-               monitors[i].wr_addr_high =
-                       RREG32(base_addr + sds->props[SP_MON_OBJ_WR_ADDR_HIGH] +
-                               i * sizeof(u32));
-
-               monitors[i].wr_data =
-                       RREG32(base_addr + sds->props[SP_MON_OBJ_WR_DATA] +
-                               i * sizeof(u32));
-
-               monitors[i].arm_data =
-                       RREG32(base_addr + sds->props[SP_MON_OBJ_ARM_DATA] +
-                               i * sizeof(u32));
-
-               monitors[i].status =
-                       RREG32(base_addr + sds->props[SP_MON_OBJ_STATUS] +
-                               i * sizeof(u32));
-       }
-
-       return monitors;
-}
-
-/**
- * hl_state_dump_free_monitors - free the monitors structure
- * @monitors: monitors array created with
- *            hl_state_dump_alloc_read_sm_block_monitors
- */
-static void hl_state_dump_free_monitors(struct hl_mon_state_dump *monitors)
-{
-       vfree(monitors);
-}
-
-/**
- * hl_state_dump_print_monitors_single_block - print active monitors on a
- * single block
- * @hdev: pointer to the device
- * @index: sync manager block index starting with E_N
- * @buf: destination buffer double pointer to be used with hl_snprintf_resize
- * @size: pointer to the size container
- * @offset: pointer to the offset container
- *
- * Returns 0 on success or error code on failure
- */
-static int hl_state_dump_print_monitors_single_block(struct hl_device *hdev,
-                                               u32 index,
-                                               char **buf, size_t *size,
-                                               size_t *offset)
-{
-       struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
-       struct hl_mon_state_dump *monitors = NULL;
-       int rc = 0, i;
-
-       if (sds->sync_namager_names) {
-               rc = hl_snprintf_resize(
-                       buf, size, offset, "%s\n",
-                       sds->sync_namager_names[index]);
-               if (rc)
-                       goto out;
-       }
-
-       monitors = hl_state_dump_alloc_read_sm_block_monitors(hdev, index);
-       if (!monitors) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       for (i = 0; i < sds->props[SP_MONITORS_AMOUNT]; ++i) {
-               if (!(sds->funcs.monitor_valid(&monitors[i])))
-                       continue;
-
-               /* Monitor is valid, dump it */
-               rc = sds->funcs.print_single_monitor(buf, size, offset, hdev,
-                                                       &monitors[i]);
-               if (rc)
-                       goto free_monitors;
-
-               hl_snprintf_resize(buf, size, offset, "\n");
-       }
-
-free_monitors:
-       hl_state_dump_free_monitors(monitors);
-out:
-       return rc;
-}
-
-/**
- * hl_state_dump_print_monitors - print active monitors
- * @hdev: pointer to the device
- * @buf: destination buffer double pointer to be used with hl_snprintf_resize
- * @size: pointer to the size container
- * @offset: pointer to the offset container
- *
- * Returns 0 on success or error code on failure
- */
-static int hl_state_dump_print_monitors(struct hl_device *hdev,
-                                       char **buf, size_t *size,
-                                       size_t *offset)
-{
-       struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
-       u32 index;
-       int rc = 0;
-
-       rc = hl_snprintf_resize(buf, size, offset,
-               "Valid (armed) monitor objects:\n");
-       if (rc)
-               goto out;
-
-       if (sds->sync_namager_names) {
-               for (index = 0; sds->sync_namager_names[index]; ++index) {
-                       rc = hl_state_dump_print_monitors_single_block(
-                               hdev, index, buf, size, offset);
-                       if (rc)
-                               goto out;
-               }
-       } else {
-               for (index = 0; index < sds->props[SP_NUM_CORES]; ++index) {
-                       rc = hl_state_dump_print_monitors_single_block(
-                               hdev, index, buf, size, offset);
-                       if (rc)
-                               goto out;
-               }
-       }
-
-out:
-       return rc;
-}
-
-/**
- * hl_state_dump_print_engine_fences - print active fences for a specific
- * engine
- * @hdev: pointer to the device
- * @engine_type: engine type to use
- * @buf: destination buffer double pointer to be used with hl_snprintf_resize
- * @size: pointer to the size container
- * @offset: pointer to the offset container
- */
-static int
-hl_state_dump_print_engine_fences(struct hl_device *hdev,
-                                 enum hl_sync_engine_type engine_type,
-                                 char **buf, size_t *size, size_t *offset)
-{
-       struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
-       int rc = 0, i, n_fences;
-       u64 base_addr, next_fence;
-
-       switch (engine_type) {
-       case ENGINE_TPC:
-               n_fences = sds->props[SP_NUM_OF_TPC_ENGINES];
-               base_addr = sds->props[SP_TPC0_CMDQ];
-               next_fence = sds->props[SP_NEXT_TPC];
-               break;
-       case ENGINE_MME:
-               n_fences = sds->props[SP_NUM_OF_MME_ENGINES];
-               base_addr = sds->props[SP_MME_CMDQ];
-               next_fence = sds->props[SP_NEXT_MME];
-               break;
-       case ENGINE_DMA:
-               n_fences = sds->props[SP_NUM_OF_DMA_ENGINES];
-               base_addr = sds->props[SP_DMA_CMDQ];
-               next_fence = sds->props[SP_DMA_QUEUES_OFFSET];
-               break;
-       default:
-               return -EINVAL;
-       }
-       for (i = 0; i < n_fences; ++i) {
-               rc = sds->funcs.print_fences_single_engine(
-                       hdev,
-                       base_addr + next_fence * i +
-                               sds->props[SP_FENCE0_CNT_OFFSET],
-                       base_addr + next_fence * i +
-                               sds->props[SP_CP_STS_OFFSET],
-                       engine_type, i, buf, size, offset);
-               if (rc)
-                       goto out;
-       }
-out:
-       return rc;
-}
-
-/**
- * hl_state_dump_print_fences - print active fences
- * @hdev: pointer to the device
- * @buf: destination buffer double pointer to be used with hl_snprintf_resize
- * @size: pointer to the size container
- * @offset: pointer to the offset container
- */
-static int hl_state_dump_print_fences(struct hl_device *hdev, char **buf,
-                                     size_t *size, size_t *offset)
-{
-       int rc = 0;
-
-       rc = hl_snprintf_resize(buf, size, offset, "Valid (armed) fences:\n");
-       if (rc)
-               goto out;
-
-       rc = hl_state_dump_print_engine_fences(hdev, ENGINE_TPC, buf, size, offset);
-       if (rc)
-               goto out;
-
-       rc = hl_state_dump_print_engine_fences(hdev, ENGINE_MME, buf, size, offset);
-       if (rc)
-               goto out;
-
-       rc = hl_state_dump_print_engine_fences(hdev, ENGINE_DMA, buf, size, offset);
-       if (rc)
-               goto out;
-
-out:
-       return rc;
-}
-
-/**
- * hl_state_dump() - dump system state
- * @hdev: pointer to device structure
- */
-int hl_state_dump(struct hl_device *hdev)
-{
-       char *buf = NULL;
-       size_t offset = 0, size = 0;
-       int rc;
-
-       rc = hl_snprintf_resize(&buf, &size, &offset,
-                               "Timestamp taken on: %llu\n\n",
-                               ktime_to_ns(ktime_get()));
-       if (rc)
-               goto err;
-
-       rc = hl_state_dump_print_syncs(hdev, &buf, &size, &offset);
-       if (rc)
-               goto err;
-
-       hl_snprintf_resize(&buf, &size, &offset, "\n");
-
-       rc = hl_state_dump_print_monitors(hdev, &buf, &size, &offset);
-       if (rc)
-               goto err;
-
-       hl_snprintf_resize(&buf, &size, &offset, "\n");
-
-       rc = hl_state_dump_print_fences(hdev, &buf, &size, &offset);
-       if (rc)
-               goto err;
-
-       hl_snprintf_resize(&buf, &size, &offset, "\n");
-
-       hl_debugfs_set_state_dump(hdev, buf, size);
-
-       return 0;
-err:
-       vfree(buf);
-       return rc;
-}