Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  dae_main.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2024 HiSilicon Limited. */

#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/uacce.h>
#include "zip.h"

/* memory */
#define DAE_MEM_START_OFFSET  0x331040
#define DAE_MEM_DONE_OFFSET  0x331044
#define DAE_MEM_START_MASK  0x1
#define DAE_MEM_DONE_MASK  0x1
#define DAE_REG_RD_INTVRL_US  10
#define DAE_REG_RD_TMOUT_US  USEC_PER_SEC

#define DAE_ALG_NAME   "hashagg"

/* error */
#define DAE_AXI_CFG_OFFSET  0x331000
#define DAE_AXI_SHUTDOWN_MASK  (BIT(0) | BIT(5))
#define DAE_ERR_SOURCE_OFFSET  0x331C84
#define DAE_ERR_STATUS_OFFSET  0x331C88
#define DAE_ERR_CE_OFFSET  0x331CA0
#define DAE_ERR_CE_MASK   BIT(3)
#define DAE_ERR_NFE_OFFSET  0x331CA4
#define DAE_ERR_NFE_MASK  0x17
#define DAE_ERR_FE_OFFSET  0x331CA8
#define DAE_ERR_FE_MASK   0
#define DAE_ECC_MBIT_MASK  BIT(2)
#define DAE_ECC_INFO_OFFSET  0x33400C
#define DAE_ERR_SHUTDOWN_OFFSET  0x331CAC
#define DAE_ERR_SHUTDOWN_MASK  0x17
#define DAE_ERR_ENABLE_OFFSET  0x331C80
#define DAE_ERR_ENABLE_MASK  (DAE_ERR_FE_MASK | DAE_ERR_NFE_MASK | DAE_ERR_CE_MASK)
#define DAE_AM_CTRL_GLOBAL_OFFSET 0x330000
#define DAE_AM_RETURN_OFFSET  0x330150
#define DAE_AM_RETURN_MASK  0x3
#define DAE_AXI_CFG_OFFSET  0x331000
#define DAE_AXI_SHUTDOWN_EN_MASK (BIT(0) | BIT(5))

struct hisi_dae_hw_error {
 u32 int_msk;
 const char *msg;
};

static const struct hisi_dae_hw_error dae_hw_error[] = {
 { .int_msk = BIT(0), .msg = "dae_axi_bus_err" },
 { .int_msk = BIT(1), .msg = "dae_axi_poison_err" },
 { .int_msk = BIT(2), .msg = "dae_ecc_2bit_err" },
 { .int_msk = BIT(3), .msg = "dae_ecc_1bit_err" },
 { .int_msk = BIT(4), .msg = "dae_fsm_hbeat_err" },
};

static inline bool dae_is_support(struct hisi_qm *qm)
{
 if (test_bit(QM_SUPPORT_DAE, &qm->caps))
  return true;

 return false;
}

int hisi_dae_set_user_domain(struct hisi_qm *qm)
{
 u32 val;
 int ret;

 if (!dae_is_support(qm))
  return 0;

 val = readl(qm->io_base + DAE_MEM_START_OFFSET);
 val |= DAE_MEM_START_MASK;
 writel(val, qm->io_base + DAE_MEM_START_OFFSET);
 ret = readl_relaxed_poll_timeout(qm->io_base + DAE_MEM_DONE_OFFSET, val,
      val & DAE_MEM_DONE_MASK,
      DAE_REG_RD_INTVRL_US, DAE_REG_RD_TMOUT_US);
 if (ret)
  pci_err(qm->pdev, "failed to init dae memory!\n");

 return ret;
}

int hisi_dae_set_alg(struct hisi_qm *qm)
{
 size_t len;

 if (!dae_is_support(qm))
  return 0;

 if (!qm->uacce)
  return 0;

 len = strlen(qm->uacce->algs);
 /* A line break may be required */
 if (len + strlen(DAE_ALG_NAME) + 1 >= QM_DEV_ALG_MAX_LEN) {
  pci_err(qm->pdev, "algorithm name is too long!\n");
  return -EINVAL;
 }

 if (len)
  strcat((char *)qm->uacce->algs, "\n");

 strcat((char *)qm->uacce->algs, DAE_ALG_NAME);

 return 0;
}

static void hisi_dae_master_ooo_ctrl(struct hisi_qm *qm, bool enable)
{
 u32 axi_val, err_val;

 axi_val = readl(qm->io_base + DAE_AXI_CFG_OFFSET);
 if (enable) {
  axi_val |= DAE_AXI_SHUTDOWN_MASK;
  err_val = DAE_ERR_SHUTDOWN_MASK;
 } else {
  axi_val &= ~DAE_AXI_SHUTDOWN_MASK;
  err_val = 0;
 }

 writel(axi_val, qm->io_base + DAE_AXI_CFG_OFFSET);
 writel(err_val, qm->io_base + DAE_ERR_SHUTDOWN_OFFSET);
}

void hisi_dae_hw_error_enable(struct hisi_qm *qm)
{
 if (!dae_is_support(qm))
  return;

 /* clear dae hw error source if having */
 writel(DAE_ERR_ENABLE_MASK, qm->io_base + DAE_ERR_SOURCE_OFFSET);

 /* configure error type */
 writel(DAE_ERR_CE_MASK, qm->io_base + DAE_ERR_CE_OFFSET);
 writel(DAE_ERR_NFE_MASK, qm->io_base + DAE_ERR_NFE_OFFSET);
 writel(DAE_ERR_FE_MASK, qm->io_base + DAE_ERR_FE_OFFSET);

 hisi_dae_master_ooo_ctrl(qm, true);

 /* enable dae hw error interrupts */
 writel(DAE_ERR_ENABLE_MASK, qm->io_base + DAE_ERR_ENABLE_OFFSET);
}

void hisi_dae_hw_error_disable(struct hisi_qm *qm)
{
 if (!dae_is_support(qm))
  return;

 writel(0, qm->io_base + DAE_ERR_ENABLE_OFFSET);
 hisi_dae_master_ooo_ctrl(qm, false);
}

static u32 hisi_dae_get_hw_err_status(struct hisi_qm *qm)
{
 return readl(qm->io_base + DAE_ERR_STATUS_OFFSET);
}

static void hisi_dae_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts)
{
 if (!dae_is_support(qm))
  return;

 writel(err_sts, qm->io_base + DAE_ERR_SOURCE_OFFSET);
}

static void hisi_dae_disable_error_report(struct hisi_qm *qm, u32 err_type)
{
 writel(DAE_ERR_NFE_MASK & (~err_type), qm->io_base + DAE_ERR_NFE_OFFSET);
}

static void hisi_dae_log_hw_error(struct hisi_qm *qm, u32 err_type)
{
 const struct hisi_dae_hw_error *err = dae_hw_error;
 struct device *dev = &qm->pdev->dev;
 u32 ecc_info;
 size_t i;

 for (i = 0; i < ARRAY_SIZE(dae_hw_error); i++) {
  err = &dae_hw_error[i];
  if (!(err->int_msk & err_type))
   continue;

  dev_err(dev, "%s [error status=0x%x] found\n",
   err->msg, err->int_msk);

  if (err->int_msk & DAE_ECC_MBIT_MASK) {
   ecc_info = readl(qm->io_base + DAE_ECC_INFO_OFFSET);
   dev_err(dev, "dae multi ecc sram info 0x%x\n", ecc_info);
  }
 }
}

enum acc_err_result hisi_dae_get_err_result(struct hisi_qm *qm)
{
 u32 err_status;

 if (!dae_is_support(qm))
  return ACC_ERR_NONE;

 err_status = hisi_dae_get_hw_err_status(qm);
 if (!err_status)
  return ACC_ERR_NONE;

 hisi_dae_log_hw_error(qm, err_status);

 if (err_status & DAE_ERR_NFE_MASK) {
  /* Disable the same error reporting until device is recovered. */
  hisi_dae_disable_error_report(qm, err_status);
  return ACC_ERR_NEED_RESET;
 }
 hisi_dae_clear_hw_err_status(qm, err_status);

 return ACC_ERR_RECOVERED;
}

bool hisi_dae_dev_is_abnormal(struct hisi_qm *qm)
{
 u32 err_status;

 if (!dae_is_support(qm))
  return false;

 err_status = hisi_dae_get_hw_err_status(qm);
 if (err_status & DAE_ERR_NFE_MASK)
  return true;

 return false;
}

int hisi_dae_close_axi_master_ooo(struct hisi_qm *qm)
{
 u32 val;
 int ret;

 if (!dae_is_support(qm))
  return 0;

 val = readl(qm->io_base + DAE_AM_CTRL_GLOBAL_OFFSET);
 val |= BIT(0);
 writel(val, qm->io_base + DAE_AM_CTRL_GLOBAL_OFFSET);

 ret = readl_relaxed_poll_timeout(qm->io_base + DAE_AM_RETURN_OFFSET,
      val, (val == DAE_AM_RETURN_MASK),
      DAE_REG_RD_INTVRL_US, DAE_REG_RD_TMOUT_US);
 if (ret)
  dev_err(&qm->pdev->dev, "failed to close dae axi ooo!\n");

 return ret;
}

void hisi_dae_open_axi_master_ooo(struct hisi_qm *qm)
{
 u32 val;

 if (!dae_is_support(qm))
  return;

 val = readl(qm->io_base + DAE_AXI_CFG_OFFSET);

 writel(val & ~DAE_AXI_SHUTDOWN_EN_MASK, qm->io_base + DAE_AXI_CFG_OFFSET);
 writel(val | DAE_AXI_SHUTDOWN_EN_MASK, qm->io_base + DAE_AXI_CFG_OFFSET);
}

Messung V0.5
C=98 H=94 G=95

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge