drivers/accel/habanalabs/common/firmware_if.c

Source file repositories/reference/linux-study-clean/drivers/accel/habanalabs/common/firmware_if.c

File Facts

System
Linux kernel
Corpus path
drivers/accel/habanalabs/common/firmware_if.c
Extension
.c
Size
93636 bytes
Lines
3338
Domain
Driver Families
Bucket
drivers/accel
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!hl_device_operational(hdev, NULL) && !hdev->reset_info.in_compute_reset) {
			dev_dbg(hdev->dev, "Device CPU packet timeout (0x%x) due to FW reset\n",
					tmp);
		} else {
			struct hl_bd *bd = queue->kernel_address;

			bd += hl_pi_2_offset(pi);

			dev_err(hdev->dev, "Device CPU packet timeout (status = 0x%x)\n"
				"Pkt info[%u]: dma_addr: 0x%llx, kernel_addr: %p, len:0x%x, ctl: 0x%x, ptr:0x%llx, dram_bd:%u\n",
				tmp, pi, pkt_dma_addr, (void *)pkt, bd->len, bd->ctl, bd->ptr,
				queue->dram_bd);
		}
		hdev->device_cpu_disabled = true;
		goto out;
	}

	tmp = le32_to_cpu(pkt->ctl);

	fw_rc = (tmp & CPUCP_PKT_CTL_RC_MASK) >> CPUCP_PKT_CTL_RC_SHIFT;
	if (fw_rc) {
		opcode = (tmp & CPUCP_PKT_CTL_OPCODE_MASK) >> CPUCP_PKT_CTL_OPCODE_SHIFT;

		if (!prop->supports_advanced_cpucp_rc) {
			dev_dbg(hdev->dev, "F/W ERROR %d for CPU packet %d\n", rc, opcode);
			rc = -EIO;
			goto scrub_descriptor;
		}

		switch (fw_rc) {
		case cpucp_packet_invalid:
			dev_err(hdev->dev,
				"CPU packet %d is not supported by F/W\n", opcode);
			break;
		case cpucp_packet_fault:
			dev_err(hdev->dev,
				"F/W failed processing CPU packet %d\n", opcode);
			break;
		case cpucp_packet_invalid_pkt:
			dev_dbg(hdev->dev,
				"CPU packet %d is not supported by F/W\n", opcode);
			break;
		case cpucp_packet_invalid_params:
			dev_err(hdev->dev,
				"F/W reports invalid parameters for CPU packet %d\n", opcode);
			break;

		default:
			dev_err(hdev->dev,
				"Unknown F/W ERROR %d for CPU packet %d\n", rc, opcode);
		}

		/* propagate the return code from the f/w to the callers who want to check it */
		if (result)
			*result = fw_rc;

		rc = -EIO;

	} else if (result) {
		*result = le64_to_cpu(pkt->result);
	}

scrub_descriptor:
	/* Scrub previous buffer descriptor 'ctl' field which contains the
	 * previous PI value written during packet submission.
	 * We must do this or else F/W can read an old value upon queue wraparound.
	 */
	sent_bd = queue->kernel_address;
	sent_bd += hl_pi_2_offset(pi);
	sent_bd->ctl = cpu_to_le32(UINT_MAX);

out:
	mutex_unlock(&hdev->send_cpu_message_lock);

	hl_cpu_accessible_dma_pool_free(hdev, size, pkt);

	return rc;
}

int hl_fw_unmask_irq(struct hl_device *hdev, u16 event_type)
{
	struct cpucp_packet pkt;
	u64 result;
	int rc;

	memset(&pkt, 0, sizeof(pkt));

	pkt.ctl = cpu_to_le32(CPUCP_PACKET_UNMASK_RAZWI_IRQ <<
				CPUCP_PKT_CTL_OPCODE_SHIFT);
	pkt.value = cpu_to_le64(event_type);

Annotation

Implementation Notes