static int device_early_init()

in habanalabs/common/device.c [354:480]


static int device_early_init(struct hl_device *hdev)
{
	int i, rc;
	char workq_name[32];

	switch (hdev->asic_type) {
	case ASIC_GOYA:
		goya_set_asic_funcs(hdev);
		strscpy(hdev->asic_name, "GOYA", sizeof(hdev->asic_name));
		break;
	case ASIC_GAUDI:
		gaudi_set_asic_funcs(hdev);
		strscpy(hdev->asic_name, "GAUDI", sizeof(hdev->asic_name));
		break;
	case ASIC_GAUDI_SEC:
		gaudi_set_asic_funcs(hdev);
		strscpy(hdev->asic_name, "GAUDI SEC", sizeof(hdev->asic_name));
		break;
	default:
		dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
			hdev->asic_type);
		return -EINVAL;
	}

	rc = hdev->asic_funcs->early_init(hdev);
	if (rc)
		return rc;

	rc = hl_asid_init(hdev);
	if (rc)
		goto early_fini;

	if (hdev->asic_prop.completion_queues_count) {
		hdev->cq_wq = kcalloc(hdev->asic_prop.completion_queues_count,
				sizeof(*hdev->cq_wq),
				GFP_KERNEL);
		if (!hdev->cq_wq) {
			rc = -ENOMEM;
			goto asid_fini;
		}
	}

	for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++) {
		snprintf(workq_name, 32, "hl-free-jobs-%u", (u32) i);
		hdev->cq_wq[i] = create_singlethread_workqueue(workq_name);
		if (hdev->cq_wq[i] == NULL) {
			dev_err(hdev->dev, "Failed to allocate CQ workqueue\n");
			rc = -ENOMEM;
			goto free_cq_wq;
		}
	}

	hdev->eq_wq = alloc_workqueue("hl-events", WQ_UNBOUND, 0);
	if (hdev->eq_wq == NULL) {
		dev_err(hdev->dev, "Failed to allocate EQ workqueue\n");
		rc = -ENOMEM;
		goto free_cq_wq;
	}

	hdev->sob_reset_wq = alloc_workqueue("hl-sob-reset", WQ_UNBOUND, 0);
	if (!hdev->sob_reset_wq) {
		dev_err(hdev->dev,
			"Failed to allocate SOB reset workqueue\n");
		rc = -ENOMEM;
		goto free_eq_wq;
	}

	hdev->hl_chip_info = kzalloc(sizeof(struct hwmon_chip_info),
					GFP_KERNEL);
	if (!hdev->hl_chip_info) {
		rc = -ENOMEM;
		goto free_sob_reset_wq;
	}

	rc = hl_mmu_if_set_funcs(hdev);
	if (rc)
		goto free_chip_info;

	hl_cb_mgr_init(&hdev->kernel_cb_mgr);

	hdev->device_reset_work.wq =
			create_singlethread_workqueue("hl_device_reset");
	if (!hdev->device_reset_work.wq) {
		rc = -ENOMEM;
		dev_err(hdev->dev, "Failed to create device reset WQ\n");
		goto free_cb_mgr;
	}

	INIT_DELAYED_WORK(&hdev->device_reset_work.reset_work,
			device_hard_reset_pending);
	hdev->device_reset_work.hdev = hdev;
	hdev->device_fini_pending = 0;

	mutex_init(&hdev->send_cpu_message_lock);
	mutex_init(&hdev->debug_lock);
	INIT_LIST_HEAD(&hdev->cs_mirror_list);
	spin_lock_init(&hdev->cs_mirror_lock);
	spin_lock_init(&hdev->reset_info.lock);
	INIT_LIST_HEAD(&hdev->fpriv_list);
	INIT_LIST_HEAD(&hdev->fpriv_ctrl_list);
	mutex_init(&hdev->fpriv_list_lock);
	mutex_init(&hdev->fpriv_ctrl_list_lock);
	mutex_init(&hdev->clk_throttling.lock);

	return 0;

free_cb_mgr:
	hl_cb_mgr_fini(hdev, &hdev->kernel_cb_mgr);
free_chip_info:
	kfree(hdev->hl_chip_info);
free_sob_reset_wq:
	destroy_workqueue(hdev->sob_reset_wq);
free_eq_wq:
	destroy_workqueue(hdev->eq_wq);
free_cq_wq:
	for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++)
		if (hdev->cq_wq[i])
			destroy_workqueue(hdev->cq_wq[i]);
	kfree(hdev->cq_wq);
asid_fini:
	hl_asid_fini(hdev);
early_fini:
	if (hdev->asic_funcs->early_fini)
		hdev->asic_funcs->early_fini(hdev);

	return rc;
}