Commit 28bcf1fd authored by Oded Gabbay's avatar Oded Gabbay
Browse files

habanalabs: enable F/W events after init done



Only after the initialization of the device is done, the driver is
ready to receive events from the F/W. The driver can't handle events
before that because of races so it will ignore events. In case of
a fatal event, the driver won't know about it and the device will be
operational although it shouldn't be.

Same logic should be applied after hard-reset.

Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent b520ca5d
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -1159,12 +1159,20 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset,
	atomic_set(&hdev->in_reset, 0);
	hdev->needs_reset = false;

	if (hard_reset)
	dev_notice(hdev->dev, "Successfully finished resetting the device\n");

	if (hard_reset) {
		hdev->hard_reset_cnt++;
	else
		hdev->soft_reset_cnt++;

	dev_warn(hdev->dev, "Successfully finished resetting the device\n");
		/* After reset is done, we are ready to receive events from
		 * the F/W. We can't do it before because we will ignore events
		 * and if those events are fatal, we won't know about it and
		 * the device will be operational although it shouldn't be
		 */
		hdev->asic_funcs->enable_events_from_fw(hdev);
	} else {
		hdev->soft_reset_cnt++;
	}

	return 0;

@@ -1415,6 +1423,13 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)

	hdev->init_done = true;

	/* After initialization is done, we are ready to receive events from
	 * the F/W. We can't do it before because we will ignore events and if
	 * those events are fatal, we won't know about it and the device will
	 * be operational although it shouldn't be
	 */
	hdev->asic_funcs->enable_events_from_fw(hdev);

	return 0;

release_ctx:
+7 −2
Original line number Diff line number Diff line
@@ -866,6 +866,10 @@ enum div_select_defs {
 * @ack_protection_bits_errors: ack and dump all security violations
 * @get_hw_block_id: retrieve a HW block id to be used by the user to mmap it.
 * @hw_block_mmap: mmap a HW block with a given id.
 * @enable_events_from_fw: send interrupt to firmware to notify them the
 *                         driver is ready to receive asynchronous events. This
 *                         function should be called during the first init and
 *                         after every hard-reset of the device
 */
struct hl_asic_funcs {
	int (*early_init)(struct hl_device *hdev);
@@ -982,6 +986,7 @@ struct hl_asic_funcs {
			u32 *block_id);
	int (*hw_block_mmap)(struct hl_device *hdev, struct vm_area_struct *vma,
			u32 block_id, u32 block_size);
	void (*enable_events_from_fw)(struct hl_device *hdev);
};


+7 −3
Original line number Diff line number Diff line
@@ -1383,8 +1383,6 @@ static int gaudi_late_init(struct hl_device *hdev)
		return rc;
	}

	WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR, GAUDI_EVENT_INTS_REGISTER);

	rc = gaudi_fetch_psoc_frequency(hdev);
	if (rc) {
		dev_err(hdev->dev, "Failed to fetch psoc frequency\n");
@@ -8500,6 +8498,11 @@ static int gaudi_block_mmap(struct hl_device *hdev,
	return -EPERM;
}

static void gaudi_enable_events_from_fw(struct hl_device *hdev)
{
	WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR, GAUDI_EVENT_INTS_REGISTER);
}

static const struct hl_asic_funcs gaudi_funcs = {
	.early_init = gaudi_early_init,
	.early_fini = gaudi_early_fini,
@@ -8581,7 +8584,8 @@ static const struct hl_asic_funcs gaudi_funcs = {
	.descramble_addr = hl_mmu_descramble_addr,
	.ack_protection_bits_errors = gaudi_ack_protection_bits_errors,
	.get_hw_block_id = gaudi_get_hw_block_id,
	.hw_block_mmap = gaudi_block_mmap
	.hw_block_mmap = gaudi_block_mmap,
	.enable_events_from_fw = gaudi_enable_events_from_fw
};

/**
+8 −4
Original line number Diff line number Diff line
@@ -798,9 +798,6 @@ int goya_late_init(struct hl_device *hdev)
		return rc;
	}

	WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR,
			GOYA_ASYNC_EVENT_ID_INTS_REGISTER);

	return 0;
}

@@ -5400,6 +5397,12 @@ static int goya_block_mmap(struct hl_device *hdev, struct vm_area_struct *vma,
	return -EPERM;
}

static void goya_enable_events_from_fw(struct hl_device *hdev)
{
	WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR,
			GOYA_ASYNC_EVENT_ID_INTS_REGISTER);
}

static const struct hl_asic_funcs goya_funcs = {
	.early_init = goya_early_init,
	.early_fini = goya_early_fini,
@@ -5481,7 +5484,8 @@ static const struct hl_asic_funcs goya_funcs = {
	.descramble_addr = hl_mmu_descramble_addr,
	.ack_protection_bits_errors = goya_ack_protection_bits_errors,
	.get_hw_block_id = goya_get_hw_block_id,
	.hw_block_mmap = goya_block_mmap
	.hw_block_mmap = goya_block_mmap,
	.enable_events_from_fw = goya_enable_events_from_fw
};

/*