opnsense-src/sys/dev/qat/qat_common/adf_dev_err.c
Julian Grajkowski 78ee8d1c4c qat: Import a new Intel (R) QAT driver
QAT in-tree driver ported from out-of-tree release available
from 01.org.

The driver exposes complete cryptography and data compression
API in the kernel and integrates with Open Crypto Framework.
Details of supported operations, devices and usage can be found
in man and on 01.org.

Patch co-authored by: Krzysztof Zdziarski <krzysztofx.zdziarski@intel.com>
Patch co-authored by: Michal Jaraczewski <michalx.jaraczewski@intel.com>
Patch co-authored by: Michal Gulbicki <michalx.gulbicki@intel.com>
Patch co-authored by: Julian Grajkowski <julianx.grajkowski@intel.com>
Patch co-authored by: Piotr Kasierski <piotrx.kasierski@intel.com>
Patch co-authored by: Adam Czupryna <adamx.czupryna@intel.com>
Patch co-authored by: Konrad Zelazny <konradx.zelazny@intel.com>
Patch co-authored by: Katarzyna Rucinska <katarzynax.kargol@intel.com>
Patch co-authored by: Lukasz Kolodzinski <lukaszx.kolodzinski@intel.com>
Patch co-authored by: Zbigniew Jedlinski <zbigniewx.jedlinski@intel.com>

Reviewed by:	markj, jhb (OCF integration)
Reviewed by:	debdrup, pauamma (docs)
Sponsored by:	Intel Corporation
Differential Revision: https://reviews.freebsd.org/D34632
2022-07-27 11:12:35 -04:00

319 lines
8.4 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright(c) 2007-2022 Intel Corporation */
/* $FreeBSD$ */
#include "adf_dev_err.h"
struct reg_info {
size_t offs;
char *name;
};
static struct reg_info adf_err_regs[] = {
{ ADF_ERRSOU0, "ERRSOU0" },
{ ADF_ERRSOU1, "ERRSOU1" },
{ ADF_ERRSOU3, "ERRSOU3" },
{ ADF_ERRSOU4, "ERRSOU4" },
{ ADF_ERRSOU5, "ERRSOU5" },
{ ADF_RICPPINTSTS, "RICPPINTSTS" },
{ ADF_RIERRPUSHID, "RIERRPUSHID" },
{ ADF_RIERRPULLID, "RIERRPULLID" },
{ ADF_CPP_CFC_ERR_STATUS, "CPP_CFC_ERR_STATUS" },
{ ADF_CPP_CFC_ERR_PPID, "CPP_CFC_ERR_PPID" },
{ ADF_TICPPINTSTS, "TICPPINTSTS" },
{ ADF_TIERRPUSHID, "TIERRPUSHID" },
{ ADF_TIERRPULLID, "TIERRPULLID" },
{ ADF_SECRAMUERR, "SECRAMUERR" },
{ ADF_SECRAMUERRAD, "SECRAMUERRAD" },
{ ADF_CPPMEMTGTERR, "CPPMEMTGTERR" },
{ ADF_ERRPPID, "ERRPPID" },
};
static u32
adf_get_intstatsssm(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_INTSTATSSM(dev));
}
static u32
adf_get_pperr(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_PPERR(dev));
}
static u32
adf_get_pperrid(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_PPERRID(dev));
}
static u32
adf_get_uerrssmsh(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMSH(dev));
}
static u32
adf_get_uerrssmshad(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMSHAD(dev));
}
static u32
adf_get_uerrssmmmp0(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 0));
}
static u32
adf_get_uerrssmmmp1(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 1));
}
static u32
adf_get_uerrssmmmp2(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 2));
}
static u32
adf_get_uerrssmmmp3(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 3));
}
static u32
adf_get_uerrssmmmp4(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 4));
}
static u32
adf_get_uerrssmmmpad0(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 0));
}
static u32
adf_get_uerrssmmmpad1(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 1));
}
static u32
adf_get_uerrssmmmpad2(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 2));
}
static u32
adf_get_uerrssmmmpad3(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 3));
}
static u32
adf_get_uerrssmmmpad4(struct resource *pmisc_bar_addr, size_t dev)
{
return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 4));
}
struct reg_array_info {
u32 (*read)(struct resource *pmisc_bar_addr, size_t dev);
char *name;
};
static struct reg_array_info adf_accel_err_regs[] = {
{ adf_get_intstatsssm, "INTSTATSSM" },
{ adf_get_pperr, "PPERR" },
{ adf_get_pperrid, "PPERRID" },
{ adf_get_uerrssmsh, "UERRSSMSH" },
{ adf_get_uerrssmshad, "UERRSSMSHAD" },
{ adf_get_uerrssmmmp0, "UERRSSMMMP0" },
{ adf_get_uerrssmmmp1, "UERRSSMMMP1" },
{ adf_get_uerrssmmmp2, "UERRSSMMMP2" },
{ adf_get_uerrssmmmp3, "UERRSSMMMP3" },
{ adf_get_uerrssmmmp4, "UERRSSMMMP4" },
{ adf_get_uerrssmmmpad0, "UERRSSMMMPAD0" },
{ adf_get_uerrssmmmpad1, "UERRSSMMMPAD1" },
{ adf_get_uerrssmmmpad2, "UERRSSMMMPAD2" },
{ adf_get_uerrssmmmpad3, "UERRSSMMMPAD3" },
{ adf_get_uerrssmmmpad4, "UERRSSMMMPAD4" },
};
static char adf_printf_buf[128] = { 0 };
static size_t adf_printf_len;
static void
adf_print_flush(struct adf_accel_dev *accel_dev)
{
if (adf_printf_len > 0) {
device_printf(GET_DEV(accel_dev), "%.128s\n", adf_printf_buf);
adf_printf_len = 0;
}
}
static void
adf_print_reg(struct adf_accel_dev *accel_dev,
const char *name,
size_t idx,
u32 val)
{
adf_printf_len += snprintf(&adf_printf_buf[adf_printf_len],
sizeof(adf_printf_buf) - adf_printf_len,
"%s[%zu],%.8x,",
name,
idx,
val);
if (adf_printf_len >= 80)
adf_print_flush(accel_dev);
}
void
adf_print_err_registers(struct adf_accel_dev *accel_dev)
{
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
struct adf_bar *misc_bar =
&GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
struct resource *csr = misc_bar->virt_addr;
size_t i;
unsigned int mask;
u32 val;
for (i = 0; i < ARRAY_SIZE(adf_err_regs); ++i) {
val = ADF_CSR_RD(csr, adf_err_regs[i].offs);
adf_print_reg(accel_dev, adf_err_regs[i].name, 0, val);
}
for (i = 0; i < ARRAY_SIZE(adf_accel_err_regs); ++i) {
size_t accel;
for (accel = 0, mask = hw_data->accel_mask; mask;
accel++, mask >>= 1) {
if (!(mask & 1))
continue;
val = adf_accel_err_regs[i].read(csr, accel);
adf_print_reg(accel_dev,
adf_accel_err_regs[i].name,
accel,
val);
}
}
adf_print_flush(accel_dev);
}
static void
adf_log_slice_hang(struct adf_accel_dev *accel_dev,
u8 accel_num,
char *unit_name,
u8 unit_number)
{
device_printf(GET_DEV(accel_dev),
"CPM #%x Slice Hang Detected unit: %s%d.\n",
accel_num,
unit_name,
unit_number);
}
bool
adf_handle_slice_hang(struct adf_accel_dev *accel_dev,
u8 accel_num,
struct resource *csr,
u32 slice_hang_offset)
{
u32 slice_hang = ADF_CSR_RD(csr, slice_hang_offset);
if (!slice_hang)
return false;
if (slice_hang & ADF_SLICE_HANG_AUTH0_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Auth", 0);
if (slice_hang & ADF_SLICE_HANG_AUTH1_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Auth", 1);
if (slice_hang & ADF_SLICE_HANG_AUTH2_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Auth", 2);
if (slice_hang & ADF_SLICE_HANG_CPHR0_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Cipher", 0);
if (slice_hang & ADF_SLICE_HANG_CPHR1_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Cipher", 1);
if (slice_hang & ADF_SLICE_HANG_CPHR2_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Cipher", 2);
if (slice_hang & ADF_SLICE_HANG_CMP0_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Comp", 0);
if (slice_hang & ADF_SLICE_HANG_CMP1_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Comp", 1);
if (slice_hang & ADF_SLICE_HANG_XLT0_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Xlator", 0);
if (slice_hang & ADF_SLICE_HANG_XLT1_MASK)
adf_log_slice_hang(accel_dev, accel_num, "Xlator", 1);
if (slice_hang & ADF_SLICE_HANG_MMP0_MASK)
adf_log_slice_hang(accel_dev, accel_num, "MMP", 0);
if (slice_hang & ADF_SLICE_HANG_MMP1_MASK)
adf_log_slice_hang(accel_dev, accel_num, "MMP", 1);
if (slice_hang & ADF_SLICE_HANG_MMP2_MASK)
adf_log_slice_hang(accel_dev, accel_num, "MMP", 2);
if (slice_hang & ADF_SLICE_HANG_MMP3_MASK)
adf_log_slice_hang(accel_dev, accel_num, "MMP", 3);
if (slice_hang & ADF_SLICE_HANG_MMP4_MASK)
adf_log_slice_hang(accel_dev, accel_num, "MMP", 4);
/* Clear the associated interrupt */
ADF_CSR_WR(csr, slice_hang_offset, slice_hang);
return true;
}
/**
* adf_check_slice_hang() - Check slice hang status
*
* Return: true if a slice hange interrupt is serviced..
*/
bool
adf_check_slice_hang(struct adf_accel_dev *accel_dev)
{
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
struct adf_bar *misc_bar =
&GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
struct resource *csr = misc_bar->virt_addr;
u32 errsou3 = ADF_CSR_RD(csr, ADF_ERRSOU3);
u32 errsou5 = ADF_CSR_RD(csr, ADF_ERRSOU5);
u32 offset;
u32 accel_num;
bool handled = false;
u32 errsou[] = { errsou3, errsou3, errsou5, errsou5, errsou5 };
u32 mask[] = { ADF_EMSK3_CPM0_MASK,
ADF_EMSK3_CPM1_MASK,
ADF_EMSK5_CPM2_MASK,
ADF_EMSK5_CPM3_MASK,
ADF_EMSK5_CPM4_MASK };
unsigned int accel_mask;
for (accel_num = 0, accel_mask = hw_data->accel_mask; accel_mask;
accel_num++, accel_mask >>= 1) {
if (!(accel_mask & 1))
continue;
if (accel_num >= ARRAY_SIZE(errsou)) {
device_printf(GET_DEV(accel_dev),
"Invalid accel_num %d.\n",
accel_num);
break;
}
if (errsou[accel_num] & mask[accel_num]) {
if (ADF_CSR_RD(csr, ADF_INTSTATSSM(accel_num)) &
ADF_INTSTATSSM_SHANGERR) {
offset = ADF_SLICEHANGSTATUS(accel_num);
handled |= adf_handle_slice_hang(accel_dev,
accel_num,
csr,
offset);
}
}
}
return handled;
}