File Index
Files and directories
Sign in
FILE

decoder.c

File preview with syntax highlighting.

linux-6.19.14/drivers/accel/habanalabs/common/decoder.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  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		0x1
 14#define VCMD_IRQ_STATUS_BUSERR_MASK		0x2
 15#define VCMD_IRQ_STATUS_TIMEOUT_MASK		0x4
 16#define VCMD_IRQ_STATUS_CMDERR_MASK		0x8
 17#define VCMD_IRQ_STATUS_ABORT_MASK		0x10
 18#define VCMD_IRQ_STATUS_RESET_MASK		0x20
 19
 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}
~/ Read-only file preview.