Path: blob/master/drivers/accel/habanalabs/common/decoder.c
26436 views
// SPDX-License-Identifier: GPL-2.012/*3* Copyright 2022 HabanaLabs, Ltd.4* All Rights Reserved.5*/67#include "habanalabs.h"89#define VCMD_CONTROL_OFFSET 0x40 /* SWREG16 */10#define VCMD_IRQ_STATUS_OFFSET 0x44 /* SWREG17 */1112#define VCMD_IRQ_STATUS_ENDCMD_MASK 0x113#define VCMD_IRQ_STATUS_BUSERR_MASK 0x214#define VCMD_IRQ_STATUS_TIMEOUT_MASK 0x415#define VCMD_IRQ_STATUS_CMDERR_MASK 0x816#define VCMD_IRQ_STATUS_ABORT_MASK 0x1017#define VCMD_IRQ_STATUS_RESET_MASK 0x201819static void dec_print_abnrm_intr_source(struct hl_device *hdev, u32 irq_status)20{21const char *format = "abnormal interrupt source:%s%s%s%s%s%s\n";22char *intr_source[6] = {"Unknown", "", "", "", "", ""};23int i = 0;2425if (!irq_status)26return;2728if (irq_status & VCMD_IRQ_STATUS_ENDCMD_MASK)29intr_source[i++] = " ENDCMD";30if (irq_status & VCMD_IRQ_STATUS_BUSERR_MASK)31intr_source[i++] = " BUSERR";32if (irq_status & VCMD_IRQ_STATUS_TIMEOUT_MASK)33intr_source[i++] = " TIMEOUT";34if (irq_status & VCMD_IRQ_STATUS_CMDERR_MASK)35intr_source[i++] = " CMDERR";36if (irq_status & VCMD_IRQ_STATUS_ABORT_MASK)37intr_source[i++] = " ABORT";38if (irq_status & VCMD_IRQ_STATUS_RESET_MASK)39intr_source[i++] = " RESET";4041dev_err(hdev->dev, format, intr_source[0], intr_source[1],42intr_source[2], intr_source[3], intr_source[4], intr_source[5]);43}4445static void dec_abnrm_intr_work(struct work_struct *work)46{47struct hl_dec *dec = container_of(work, struct hl_dec, abnrm_intr_work);48struct hl_device *hdev = dec->hdev;49u32 irq_status, event_mask = 0;50bool reset_required = false;5152irq_status = RREG32(dec->base_addr + VCMD_IRQ_STATUS_OFFSET);5354dev_err(hdev->dev, "Decoder abnormal interrupt %#x, core %d\n", irq_status, dec->core_id);5556dec_print_abnrm_intr_source(hdev, irq_status);5758/* Clear the interrupt */59WREG32(dec->base_addr + VCMD_IRQ_STATUS_OFFSET, irq_status);6061/* Flush the interrupt clear */62RREG32(dec->base_addr + VCMD_IRQ_STATUS_OFFSET);6364if (irq_status & VCMD_IRQ_STATUS_TIMEOUT_MASK) {65reset_required = true;66event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR;67}6869if (irq_status & VCMD_IRQ_STATUS_CMDERR_MASK)70event_mask |= HL_NOTIFIER_EVENT_UNDEFINED_OPCODE;7172if (irq_status & (VCMD_IRQ_STATUS_ENDCMD_MASK |73VCMD_IRQ_STATUS_BUSERR_MASK |74VCMD_IRQ_STATUS_ABORT_MASK))75event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR;7677if (reset_required) {78event_mask |= HL_NOTIFIER_EVENT_DEVICE_RESET;79hl_device_cond_reset(hdev, 0, event_mask);80} else if (event_mask) {81hl_notifier_event_send_all(hdev, event_mask);82}83}8485void hl_dec_fini(struct hl_device *hdev)86{87kfree(hdev->dec);88}8990int hl_dec_init(struct hl_device *hdev)91{92struct asic_fixed_properties *prop = &hdev->asic_prop;93struct hl_dec *dec;94int rc, j;9596/* if max core is 0, nothing to do*/97if (!prop->max_dec)98return 0;99100hdev->dec = kcalloc(prop->max_dec, sizeof(struct hl_dec), GFP_KERNEL);101if (!hdev->dec)102return -ENOMEM;103104for (j = 0 ; j < prop->max_dec ; j++) {105dec = hdev->dec + j;106107dec->hdev = hdev;108INIT_WORK(&dec->abnrm_intr_work, dec_abnrm_intr_work);109dec->core_id = j;110dec->base_addr = hdev->asic_funcs->get_dec_base_addr(hdev, j);111if (!dec->base_addr) {112dev_err(hdev->dev, "Invalid base address of decoder %d\n", j);113rc = -EINVAL;114goto err_dec_fini;115}116}117118return 0;119120err_dec_fini:121hl_dec_fini(hdev);122123return rc;124}125126void hl_dec_ctx_fini(struct hl_ctx *ctx)127{128struct hl_device *hdev = ctx->hdev;129struct asic_fixed_properties *prop = &hdev->asic_prop;130struct hl_dec *dec;131int j;132133for (j = 0 ; j < prop->max_dec ; j++) {134if (!!(prop->decoder_enabled_mask & BIT(j))) {135dec = hdev->dec + j;136/* Stop the decoder */137WREG32(dec->base_addr + VCMD_CONTROL_OFFSET, 0);138}139}140}141142143