drivers/crypto/intel/qat/qat_common/adf_heartbeat.c

Source file repositories/reference/linux-study-clean/drivers/crypto/intel/qat/qat_common/adf_heartbeat.c

File Facts

System
Linux kernel
Corpus path
drivers/crypto/intel/qat/qat_common/adf_heartbeat.c
Extension
.c
Size
9325 bytes
Lines
346
Domain
Driver Families
Bucket
drivers/crypto
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 ((thr == ADF_AE_ADMIN_THREAD || req != resp) && resp == last) {
			u16 retry = ++count[thr];

			if (retry >= ADF_CFG_HB_COUNT_THRESHOLD)
				return -EIO;

		} else {
			count[thr] = 0;
		}
	}
	return 0;
}

static int adf_hb_get_status(struct adf_accel_dev *accel_dev)
{
	struct adf_hw_device_data *hw_device = accel_dev->hw_device;
	struct hb_cnt_pair *live_stats, *last_stats, *curr_stats;
	const size_t hb_ctrs = hw_device->num_hb_ctrs;
	const unsigned long ae_mask = hw_device->ae_mask;
	const size_t max_aes = hw_device->num_engines;
	const size_t dev_ctrs = size_mul(max_aes, hb_ctrs);
	const size_t stats_size = size_mul(dev_ctrs, sizeof(*curr_stats));
	struct hb_cnt_pair *ae_curr_p, *ae_prev_p;
	u16 *count_fails, *ae_count_p;
	size_t ae_offset;
	size_t ae = 0;
	int ret = 0;

	if (!accel_dev->heartbeat->ctrs_cnt_checked) {
		if (validate_hb_ctrs_cnt(accel_dev))
			hw_device->num_hb_ctrs += ADF_NUM_PKE_STRAND;

		accel_dev->heartbeat->ctrs_cnt_checked = true;
	}

	live_stats = accel_dev->heartbeat->dma.virt_addr;
	last_stats = live_stats + dev_ctrs;
	count_fails = (u16 *)(last_stats + dev_ctrs);

	curr_stats = kmemdup(live_stats, stats_size, GFP_KERNEL);
	if (!curr_stats)
		return -ENOMEM;

	/* loop through active AEs */
	for_each_set_bit(ae, &ae_mask, max_aes) {
		ae_offset = size_mul(ae, hb_ctrs);
		ae_curr_p = curr_stats + ae_offset;
		ae_prev_p = last_stats + ae_offset;
		ae_count_p = count_fails + ae_offset;

		ret = check_ae(ae_curr_p, ae_prev_p, ae_count_p, hb_ctrs);
		if (ret)
			break;
	}

	/* Copy current stats for the next iteration */
	memcpy(last_stats, curr_stats, stats_size);
	kfree(curr_stats);

	return ret;
}

static void adf_heartbeat_reset(struct adf_accel_dev *accel_dev)
{
	u64 curr_time = adf_clock_get_current_time();
	u64 time_since_reset = curr_time - accel_dev->heartbeat->last_hb_reset_time;

	if (time_since_reset < ADF_CFG_HB_RESET_MS)
		return;

	accel_dev->heartbeat->last_hb_reset_time = curr_time;
	if (adf_notify_fatal_error(accel_dev))
		dev_err(&GET_DEV(accel_dev), "Failed to notify fatal error\n");
}

void adf_heartbeat_status(struct adf_accel_dev *accel_dev,
			  enum adf_device_heartbeat_status *hb_status)
{
	struct adf_heartbeat *hb;

	if (!adf_dev_started(accel_dev) ||
	    test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) {
		*hb_status = HB_DEV_UNRESPONSIVE;
		return;
	}

	if (adf_hb_check_polling_freq(accel_dev) == -EINVAL) {
		*hb_status = HB_DEV_UNSUPPORTED;
		return;
	}

Annotation

Implementation Notes