drivers/fpga/dfl-afu-error.c

Source file repositories/reference/linux-study-clean/drivers/fpga/dfl-afu-error.c

File Facts

System
Linux kernel
Corpus path
drivers/fpga/dfl-afu-error.c
Extension
.c
Size
6375 bytes
Lines
251
Domain
Driver Families
Bucket
drivers/fpga
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

// SPDX-License-Identifier: GPL-2.0
/*
 * Driver for FPGA Accelerated Function Unit (AFU) Error Reporting
 *
 * Copyright 2019 Intel Corporation, Inc.
 *
 * Authors:
 *   Wu Hao <hao.wu@linux.intel.com>
 *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
 *   Joseph Grecco <joe.grecco@intel.com>
 *   Enno Luebbers <enno.luebbers@intel.com>
 *   Tim Whisonant <tim.whisonant@intel.com>
 *   Ananda Ravuri <ananda.ravuri@intel.com>
 *   Mitchel Henry <henry.mitchel@intel.com>
 */

#include <linux/fpga-dfl.h>
#include <linux/uaccess.h>

#include "dfl-afu.h"

#define PORT_ERROR_MASK		0x8
#define PORT_ERROR		0x10
#define PORT_FIRST_ERROR	0x18
#define PORT_MALFORMED_REQ0	0x20
#define PORT_MALFORMED_REQ1	0x28

#define ERROR_MASK		GENMASK_ULL(63, 0)

/* mask or unmask port errors by the error mask register. */
static void __afu_port_err_mask(struct dfl_feature_dev_data *fdata, bool mask)
{
	void __iomem *base;

	base = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);

	writeq(mask ? ERROR_MASK : 0, base + PORT_ERROR_MASK);
}

static void afu_port_err_mask(struct device *dev, bool mask)
{
	struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);

	mutex_lock(&fdata->lock);
	__afu_port_err_mask(fdata, mask);
	mutex_unlock(&fdata->lock);
}

/* clear port errors. */
static int afu_port_err_clear(struct device *dev, u64 err)
{
	struct dfl_feature_dev_data *fdata = to_dfl_feature_dev_data(dev);
	void __iomem *base_err, *base_hdr;
	int enable_ret = 0, ret = -EBUSY;
	u64 v;

	base_err = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_ERROR);
	base_hdr = dfl_get_feature_ioaddr_by_id(fdata, PORT_FEATURE_ID_HEADER);

	mutex_lock(&fdata->lock);

	/*
	 * clear Port Errors
	 *
	 * - Check for AP6 State
	 * - Halt Port by keeping Port in reset
	 * - Set PORT Error mask to all 1 to mask errors
	 * - Clear all errors
	 * - Set Port mask to all 0 to enable errors
	 * - All errors start capturing new errors
	 * - Enable Port by pulling the port out of reset
	 */

	/* if device is still in AP6 power state, can not clear any error. */
	v = readq(base_hdr + PORT_HDR_STS);
	if (FIELD_GET(PORT_STS_PWR_STATE, v) == PORT_STS_PWR_STATE_AP6) {
		dev_err(dev, "Could not clear errors, device in AP6 state.\n");
		goto done;
	}

	/* Halt Port by keeping Port in reset */
	ret = __afu_port_disable(fdata);
	if (ret)
		goto done;

	/* Mask all errors */
	__afu_port_err_mask(fdata, true);

	/* Clear errors if err input matches with current port errors.*/
	v = readq(base_err + PORT_ERROR);

Annotation

Implementation Notes