Skip to content

Commit

Permalink
crypto: hisilicon/qm - enable PF and VFs communication
Browse files Browse the repository at this point in the history
Kunpeng930 hardware supports the communication between PF and VFs.

This patch enables communication between PF and VFs by writing hardware
registers, and requests an irq for communication.

Signed-off-by: Weili Qian <qianweili@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Weili Qian authored and Herbert Xu committed Jun 3, 2021
1 parent 38cd396 commit e3ac4d2
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 8 deletions.
113 changes: 105 additions & 8 deletions drivers/crypto/hisilicon/qm.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
#define QM_IRQ_NUM_V1 1
#define QM_IRQ_NUM_PF_V2 4
#define QM_IRQ_NUM_VF_V2 2
#define QM_IRQ_NUM_VF_V3 3

#define QM_EQ_EVENT_IRQ_VECTOR 0
#define QM_AEQ_EVENT_IRQ_VECTOR 1
#define QM_CMD_EVENT_IRQ_VECTOR 2
#define QM_ABNORMAL_EVENT_IRQ_VECTOR 3

/* mailbox */
Expand Down Expand Up @@ -177,6 +179,16 @@
#define ACC_ROB_ECC_ERR_MULTPL BIT(1)
#define QM_MSI_CAP_ENABLE BIT(16)

/* interfunction communication */
#define QM_IFC_INT_SOURCE_P 0x100138
#define QM_IFC_INT_SOURCE_V 0x0020
#define QM_IFC_INT_MASK 0x0024
#define QM_IFC_INT_STATUS 0x0028
#define QM_IFC_INT_SOURCE_CLR GENMASK(63, 0)
#define QM_IFC_INT_SOURCE_MASK BIT(0)
#define QM_IFC_INT_DISABLE BIT(0)
#define QM_IFC_INT_STATUS_MASK BIT(0)

#define QM_DFX_MB_CNT_VF 0x104010
#define QM_DFX_DB_CNT_VF 0x104020
#define QM_DFX_SQE_CNT_VF_SQN 0x104030
Expand Down Expand Up @@ -633,6 +645,14 @@ static u32 qm_get_irq_num_v2(struct hisi_qm *qm)
return QM_IRQ_NUM_VF_V2;
}

static u32 qm_get_irq_num_v3(struct hisi_qm *qm)
{
if (qm->fun_type == QM_HW_PF)
return QM_IRQ_NUM_PF_V2;

return QM_IRQ_NUM_VF_V3;
}

static struct hisi_qp *qm_to_hisi_qp(struct hisi_qm *qm, struct qm_eqe *eqe)
{
u16 cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK;
Expand Down Expand Up @@ -737,6 +757,21 @@ static irqreturn_t qm_irq(int irq, void *data)
return IRQ_NONE;
}

static irqreturn_t qm_mb_cmd_irq(int irq, void *data)
{
struct hisi_qm *qm = data;
u32 val;

val = readl(qm->io_base + QM_IFC_INT_STATUS);
val &= QM_IFC_INT_STATUS_MASK;
if (!val)
return IRQ_NONE;

schedule_work(&qm->cmd_process);

return IRQ_HANDLED;
}

static irqreturn_t qm_aeq_irq(int irq, void *data)
{
struct hisi_qm *qm = data;
Expand Down Expand Up @@ -777,14 +812,16 @@ static void qm_irq_unregister(struct hisi_qm *qm)

free_irq(pci_irq_vector(pdev, QM_EQ_EVENT_IRQ_VECTOR), qm);

if (qm->ver == QM_HW_V1)
return;
if (qm->ver > QM_HW_V1) {
free_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR), qm);

free_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR), qm);
if (qm->fun_type == QM_HW_PF)
free_irq(pci_irq_vector(pdev,
QM_ABNORMAL_EVENT_IRQ_VECTOR), qm);
}

if (qm->fun_type == QM_HW_PF)
free_irq(pci_irq_vector(pdev,
QM_ABNORMAL_EVENT_IRQ_VECTOR), qm);
if (qm->ver > QM_HW_V2)
free_irq(pci_irq_vector(pdev, QM_CMD_EVENT_IRQ_VECTOR), qm);
}

static void qm_init_qp_status(struct hisi_qp *qp)
Expand Down Expand Up @@ -1796,6 +1833,18 @@ static int qm_check_dev_error(struct hisi_qm *qm)
(dev_val & (~qm->err_info.dev_ce_mask));
}

static void qm_clear_cmd_interrupt(struct hisi_qm *qm, u64 vf_mask)
{
u32 val;

if (qm->fun_type == QM_HW_PF)
writeq(vf_mask, qm->io_base + QM_IFC_INT_SOURCE_P);

val = readl(qm->io_base + QM_IFC_INT_SOURCE_V);
val |= QM_IFC_INT_SOURCE_MASK;
writel(val, qm->io_base + QM_IFC_INT_SOURCE_V);
}

static int qm_wait_vf_prepare_finish(struct hisi_qm *qm)
{
return 0;
Expand Down Expand Up @@ -1913,7 +1962,7 @@ static const struct hisi_qm_hw_ops qm_hw_ops_v2 = {
static const struct hisi_qm_hw_ops qm_hw_ops_v3 = {
.get_vft = qm_get_vft_v2,
.qm_db = qm_db_v2,
.get_irq_num = qm_get_irq_num_v2,
.get_irq_num = qm_get_irq_num_v3,
.hw_error_init = qm_hw_error_init_v3,
.hw_error_uninit = qm_hw_error_uninit_v3,
.hw_error_handle = qm_hw_error_handle_v2,
Expand Down Expand Up @@ -2777,6 +2826,34 @@ static void hisi_qm_pre_init(struct hisi_qm *qm)
qm->misc_ctl = false;
}

static void qm_cmd_uninit(struct hisi_qm *qm)
{
u32 val;

if (qm->ver < QM_HW_V3)
return;

val = readl(qm->io_base + QM_IFC_INT_MASK);
val |= QM_IFC_INT_DISABLE;
writel(val, qm->io_base + QM_IFC_INT_MASK);
}

static void qm_cmd_init(struct hisi_qm *qm)
{
u32 val;

if (qm->ver < QM_HW_V3)
return;

/* Clear communication interrupt source */
qm_clear_cmd_interrupt(qm, QM_IFC_INT_SOURCE_CLR);

/* Enable pf to vf communication reg. */
val = readl(qm->io_base + QM_IFC_INT_MASK);
val &= ~QM_IFC_INT_DISABLE;
writel(val, qm->io_base + QM_IFC_INT_MASK);
}

static void qm_put_pci_res(struct hisi_qm *qm)
{
struct pci_dev *pdev = qm->pdev;
Expand Down Expand Up @@ -2808,6 +2885,7 @@ void hisi_qm_uninit(struct hisi_qm *qm)
struct pci_dev *pdev = qm->pdev;
struct device *dev = &pdev->dev;

qm_cmd_uninit(qm);
down_write(&qm->qps_lock);

if (!qm_avail_state(qm, QM_CLOSE)) {
Expand Down Expand Up @@ -4331,7 +4409,7 @@ static int qm_irq_register(struct hisi_qm *qm)
if (ret)
return ret;

if (qm->ver != QM_HW_V1) {
if (qm->ver > QM_HW_V1) {
ret = request_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR),
qm_aeq_irq, 0, qm->dev_name, qm);
if (ret)
Expand All @@ -4346,8 +4424,18 @@ static int qm_irq_register(struct hisi_qm *qm)
}
}

if (qm->ver > QM_HW_V2) {
ret = request_irq(pci_irq_vector(pdev, QM_CMD_EVENT_IRQ_VECTOR),
qm_mb_cmd_irq, 0, qm->dev_name, qm);
if (ret)
goto err_mb_cmd_irq;
}

return 0;

err_mb_cmd_irq:
if (qm->fun_type == QM_HW_PF)
free_irq(pci_irq_vector(pdev, QM_ABNORMAL_EVENT_IRQ_VECTOR), qm);
err_abonormal_irq:
free_irq(pci_irq_vector(pdev, QM_AEQ_EVENT_IRQ_VECTOR), qm);
err_aeq_irq:
Expand Down Expand Up @@ -4384,6 +4472,11 @@ static void hisi_qm_controller_reset(struct work_struct *rst_work)

}

static void qm_cmd_process(struct work_struct *cmd_process)
{
/* handling messages sent by communication source */
}

/**
* hisi_qm_alg_register() - Register alg to crypto and add qm to qm_list.
* @qm: The qm needs add.
Expand Down Expand Up @@ -4615,6 +4708,10 @@ int hisi_qm_init(struct hisi_qm *qm)
if (qm->fun_type == QM_HW_PF)
INIT_WORK(&qm->rst_work, hisi_qm_controller_reset);

if (qm->ver >= QM_HW_V3)
INIT_WORK(&qm->cmd_process, qm_cmd_process);

qm_cmd_init(qm);
atomic_set(&qm->status.flags, QM_INIT);

return 0;
Expand Down
1 change: 1 addition & 0 deletions drivers/crypto/hisilicon/qm.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ struct hisi_qm {
struct workqueue_struct *wq;
struct work_struct work;
struct work_struct rst_work;
struct work_struct cmd_process;

const char *algs;
bool use_sva;
Expand Down

0 comments on commit e3ac4d2

Please sign in to comment.