cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cptvf_mbox.c (4389B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2016 Cavium, Inc.
      4 */
      5
      6#include "cptvf.h"
      7
      8static void cptvf_send_msg_to_pf(struct cpt_vf *cptvf, struct cpt_mbox *mbx)
      9{
     10	/* Writing mbox(1) causes interrupt */
     11	cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0),
     12			mbx->msg);
     13	cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1),
     14			mbx->data);
     15}
     16
     17/* Interrupt handler to handle mailbox messages from VFs */
     18void cptvf_handle_mbox_intr(struct cpt_vf *cptvf)
     19{
     20	struct cpt_mbox mbx = {};
     21
     22	/*
     23	 * MBOX[0] contains msg
     24	 * MBOX[1] contains data
     25	 */
     26	mbx.msg  = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0));
     27	mbx.data = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1));
     28	dev_dbg(&cptvf->pdev->dev, "%s: Mailbox msg 0x%llx from PF\n",
     29		__func__, mbx.msg);
     30	switch (mbx.msg) {
     31	case CPT_MSG_READY:
     32	{
     33		cptvf->pf_acked = true;
     34		cptvf->vfid = mbx.data;
     35		dev_dbg(&cptvf->pdev->dev, "Received VFID %d\n", cptvf->vfid);
     36		break;
     37	}
     38	case CPT_MSG_QBIND_GRP:
     39		cptvf->pf_acked = true;
     40		cptvf->vftype = mbx.data;
     41		dev_dbg(&cptvf->pdev->dev, "VF %d type %s group %d\n",
     42			cptvf->vfid, ((mbx.data == SE_TYPES) ? "SE" : "AE"),
     43			cptvf->vfgrp);
     44		break;
     45	case CPT_MBOX_MSG_TYPE_ACK:
     46		cptvf->pf_acked = true;
     47		break;
     48	case CPT_MBOX_MSG_TYPE_NACK:
     49		cptvf->pf_nacked = true;
     50		break;
     51	default:
     52		dev_err(&cptvf->pdev->dev, "Invalid msg from PF, msg 0x%llx\n",
     53			mbx.msg);
     54		break;
     55	}
     56}
     57
     58static int cptvf_send_msg_to_pf_timeout(struct cpt_vf *cptvf,
     59					struct cpt_mbox *mbx)
     60{
     61	int timeout = CPT_MBOX_MSG_TIMEOUT;
     62	int sleep = 10;
     63
     64	cptvf->pf_acked = false;
     65	cptvf->pf_nacked = false;
     66	cptvf_send_msg_to_pf(cptvf, mbx);
     67	/* Wait for previous message to be acked, timeout 2sec */
     68	while (!cptvf->pf_acked) {
     69		if (cptvf->pf_nacked)
     70			return -EINVAL;
     71		msleep(sleep);
     72		if (cptvf->pf_acked)
     73			break;
     74		timeout -= sleep;
     75		if (!timeout) {
     76			dev_err(&cptvf->pdev->dev, "PF didn't ack to mbox msg %llx from VF%u\n",
     77				(mbx->msg & 0xFF), cptvf->vfid);
     78			return -EBUSY;
     79		}
     80	}
     81
     82	return 0;
     83}
     84
     85/*
     86 * Checks if VF is able to comminicate with PF
     87 * and also gets the CPT number this VF is associated to.
     88 */
     89int cptvf_check_pf_ready(struct cpt_vf *cptvf)
     90{
     91	struct pci_dev *pdev = cptvf->pdev;
     92	struct cpt_mbox mbx = {};
     93
     94	mbx.msg = CPT_MSG_READY;
     95	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
     96		dev_err(&pdev->dev, "PF didn't respond to READY msg\n");
     97		return -EBUSY;
     98	}
     99
    100	return 0;
    101}
    102
    103/*
    104 * Communicate VQs size to PF to program CPT(0)_PF_Q(0-15)_CTL of the VF.
    105 * Must be ACKed.
    106 */
    107int cptvf_send_vq_size_msg(struct cpt_vf *cptvf)
    108{
    109	struct pci_dev *pdev = cptvf->pdev;
    110	struct cpt_mbox mbx = {};
    111
    112	mbx.msg = CPT_MSG_QLEN;
    113	mbx.data = cptvf->qsize;
    114	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
    115		dev_err(&pdev->dev, "PF didn't respond to vq_size msg\n");
    116		return -EBUSY;
    117	}
    118
    119	return 0;
    120}
    121
    122/*
    123 * Communicate VF group required to PF and get the VQ binded to that group
    124 */
    125int cptvf_send_vf_to_grp_msg(struct cpt_vf *cptvf)
    126{
    127	struct pci_dev *pdev = cptvf->pdev;
    128	struct cpt_mbox mbx = {};
    129
    130	mbx.msg = CPT_MSG_QBIND_GRP;
    131	/* Convey group of the VF */
    132	mbx.data = cptvf->vfgrp;
    133	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
    134		dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n");
    135		return -EBUSY;
    136	}
    137
    138	return 0;
    139}
    140
    141/*
    142 * Communicate VF group required to PF and get the VQ binded to that group
    143 */
    144int cptvf_send_vf_priority_msg(struct cpt_vf *cptvf)
    145{
    146	struct pci_dev *pdev = cptvf->pdev;
    147	struct cpt_mbox mbx = {};
    148
    149	mbx.msg = CPT_MSG_VQ_PRIORITY;
    150	/* Convey group of the VF */
    151	mbx.data = cptvf->priority;
    152	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
    153		dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n");
    154		return -EBUSY;
    155	}
    156	return 0;
    157}
    158
    159/*
    160 * Communicate to PF that VF is UP and running
    161 */
    162int cptvf_send_vf_up(struct cpt_vf *cptvf)
    163{
    164	struct pci_dev *pdev = cptvf->pdev;
    165	struct cpt_mbox mbx = {};
    166
    167	mbx.msg = CPT_MSG_VF_UP;
    168	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
    169		dev_err(&pdev->dev, "PF didn't respond to UP msg\n");
    170		return -EBUSY;
    171	}
    172
    173	return 0;
    174}
    175
    176/*
    177 * Communicate to PF that VF is DOWN and running
    178 */
    179int cptvf_send_vf_down(struct cpt_vf *cptvf)
    180{
    181	struct pci_dev *pdev = cptvf->pdev;
    182	struct cpt_mbox mbx = {};
    183
    184	mbx.msg = CPT_MSG_VF_DOWN;
    185	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
    186		dev_err(&pdev->dev, "PF didn't respond to DOWN msg\n");
    187		return -EBUSY;
    188	}
    189
    190	return 0;
    191}