brintos

brintos / linux-shallow public Read only

0
0
Text · 3.6 KiB · c03a6da Raw
142 lines · c
1// SPDX-License-Identifier: GPL-2.02 3/*4 * Copyright 2022 HabanaLabs, Ltd.5 * All Rights Reserved.6 */7 8#include "habanalabs.h"9 10#define VCMD_CONTROL_OFFSET			0x40	/* SWREG16 */11#define VCMD_IRQ_STATUS_OFFSET			0x44	/* SWREG17 */12 13#define VCMD_IRQ_STATUS_ENDCMD_MASK		0x114#define VCMD_IRQ_STATUS_BUSERR_MASK		0x215#define VCMD_IRQ_STATUS_TIMEOUT_MASK		0x416#define VCMD_IRQ_STATUS_CMDERR_MASK		0x817#define VCMD_IRQ_STATUS_ABORT_MASK		0x1018#define VCMD_IRQ_STATUS_RESET_MASK		0x2019 20static void dec_print_abnrm_intr_source(struct hl_device *hdev, u32 irq_status)21{22	const char *format = "abnormal interrupt source:%s%s%s%s%s%s\n";23	char *intr_source[6] = {"Unknown", "", "", "", "", ""};24	int i = 0;25 26	if (!irq_status)27		return;28 29	if (irq_status & VCMD_IRQ_STATUS_ENDCMD_MASK)30		intr_source[i++] = " ENDCMD";31	if (irq_status & VCMD_IRQ_STATUS_BUSERR_MASK)32		intr_source[i++] = " BUSERR";33	if (irq_status & VCMD_IRQ_STATUS_TIMEOUT_MASK)34		intr_source[i++] = " TIMEOUT";35	if (irq_status & VCMD_IRQ_STATUS_CMDERR_MASK)36		intr_source[i++] = " CMDERR";37	if (irq_status & VCMD_IRQ_STATUS_ABORT_MASK)38		intr_source[i++] = " ABORT";39	if (irq_status & VCMD_IRQ_STATUS_RESET_MASK)40		intr_source[i++] = " RESET";41 42	dev_err(hdev->dev, format, intr_source[0], intr_source[1],43		intr_source[2], intr_source[3], intr_source[4], intr_source[5]);44}45 46static void dec_abnrm_intr_work(struct work_struct *work)47{48	struct hl_dec *dec = container_of(work, struct hl_dec, abnrm_intr_work);49	struct hl_device *hdev = dec->hdev;50	u32 irq_status, event_mask = 0;51	bool reset_required = false;52 53	irq_status = RREG32(dec->base_addr + VCMD_IRQ_STATUS_OFFSET);54 55	dev_err(hdev->dev, "Decoder abnormal interrupt %#x, core %d\n", irq_status, dec->core_id);56 57	dec_print_abnrm_intr_source(hdev, irq_status);58 59	/* Clear the interrupt */60	WREG32(dec->base_addr + VCMD_IRQ_STATUS_OFFSET, irq_status);61 62	/* Flush the interrupt clear */63	RREG32(dec->base_addr + VCMD_IRQ_STATUS_OFFSET);64 65	if (irq_status & VCMD_IRQ_STATUS_TIMEOUT_MASK) {66		reset_required = true;67		event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR;68	}69 70	if (irq_status & VCMD_IRQ_STATUS_CMDERR_MASK)71		event_mask |= HL_NOTIFIER_EVENT_UNDEFINED_OPCODE;72 73	if (irq_status & (VCMD_IRQ_STATUS_ENDCMD_MASK |74				VCMD_IRQ_STATUS_BUSERR_MASK |75				VCMD_IRQ_STATUS_ABORT_MASK))76		event_mask |= HL_NOTIFIER_EVENT_USER_ENGINE_ERR;77 78	if (reset_required) {79		event_mask |= HL_NOTIFIER_EVENT_DEVICE_RESET;80		hl_device_cond_reset(hdev, 0, event_mask);81	} else if (event_mask) {82		hl_notifier_event_send_all(hdev, event_mask);83	}84}85 86void hl_dec_fini(struct hl_device *hdev)87{88	kfree(hdev->dec);89}90 91int hl_dec_init(struct hl_device *hdev)92{93	struct asic_fixed_properties *prop = &hdev->asic_prop;94	struct hl_dec *dec;95	int rc, j;96 97	/* if max core is 0, nothing to do*/98	if (!prop->max_dec)99		return 0;100 101	hdev->dec = kcalloc(prop->max_dec, sizeof(struct hl_dec), GFP_KERNEL);102	if (!hdev->dec)103		return -ENOMEM;104 105	for (j = 0 ; j < prop->max_dec ; j++) {106		dec = hdev->dec + j;107 108		dec->hdev = hdev;109		INIT_WORK(&dec->abnrm_intr_work, dec_abnrm_intr_work);110		dec->core_id = j;111		dec->base_addr = hdev->asic_funcs->get_dec_base_addr(hdev, j);112		if (!dec->base_addr) {113			dev_err(hdev->dev, "Invalid base address of decoder %d\n", j);114			rc = -EINVAL;115			goto err_dec_fini;116		}117	}118 119	return 0;120 121err_dec_fini:122	hl_dec_fini(hdev);123 124	return rc;125}126 127void hl_dec_ctx_fini(struct hl_ctx *ctx)128{129	struct hl_device *hdev = ctx->hdev;130	struct asic_fixed_properties *prop = &hdev->asic_prop;131	struct hl_dec *dec;132	int j;133 134	for (j = 0 ; j < prop->max_dec ; j++) {135		if (!!(prop->decoder_enabled_mask & BIT(j))) {136			dec = hdev->dec + j;137			/* Stop the decoder */138			WREG32(dec->base_addr + VCMD_CONTROL_OFFSET, 0);139		}140	}141}142