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

otx_cptvf_mbox.c (5326B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Marvell OcteonTX CPT driver
      3 *
      4 * Copyright (C) 2019 Marvell International Ltd.
      5 *
      6 * This program is free software; you can redistribute it and/or modify
      7 * it under the terms of the GNU General Public License version 2 as
      8 * published by the Free Software Foundation.
      9 */
     10
     11#include <linux/delay.h>
     12#include "otx_cptvf.h"
     13
     14#define CPT_MBOX_MSG_TIMEOUT 2000
     15
     16static char *get_mbox_opcode_str(int msg_opcode)
     17{
     18	char *str = "Unknown";
     19
     20	switch (msg_opcode) {
     21	case OTX_CPT_MSG_VF_UP:
     22		str = "UP";
     23		break;
     24
     25	case OTX_CPT_MSG_VF_DOWN:
     26		str = "DOWN";
     27		break;
     28
     29	case OTX_CPT_MSG_READY:
     30		str = "READY";
     31		break;
     32
     33	case OTX_CPT_MSG_QLEN:
     34		str = "QLEN";
     35		break;
     36
     37	case OTX_CPT_MSG_QBIND_GRP:
     38		str = "QBIND_GRP";
     39		break;
     40
     41	case OTX_CPT_MSG_VQ_PRIORITY:
     42		str = "VQ_PRIORITY";
     43		break;
     44
     45	case OTX_CPT_MSG_PF_TYPE:
     46		str = "PF_TYPE";
     47		break;
     48
     49	case OTX_CPT_MSG_ACK:
     50		str = "ACK";
     51		break;
     52
     53	case OTX_CPT_MSG_NACK:
     54		str = "NACK";
     55		break;
     56	}
     57	return str;
     58}
     59
     60static void dump_mbox_msg(struct otx_cpt_mbox *mbox_msg, int vf_id)
     61{
     62	char raw_data_str[OTX_CPT_MAX_MBOX_DATA_STR_SIZE];
     63
     64	hex_dump_to_buffer(mbox_msg, sizeof(struct otx_cpt_mbox), 16, 8,
     65			   raw_data_str, OTX_CPT_MAX_MBOX_DATA_STR_SIZE, false);
     66	if (vf_id >= 0)
     67		pr_debug("MBOX msg %s received from VF%d raw_data %s",
     68			 get_mbox_opcode_str(mbox_msg->msg), vf_id,
     69			 raw_data_str);
     70	else
     71		pr_debug("MBOX msg %s received from PF raw_data %s",
     72			 get_mbox_opcode_str(mbox_msg->msg), raw_data_str);
     73}
     74
     75static void cptvf_send_msg_to_pf(struct otx_cptvf *cptvf,
     76				     struct otx_cpt_mbox *mbx)
     77{
     78	/* Writing mbox(1) causes interrupt */
     79	writeq(mbx->msg, cptvf->reg_base + OTX_CPT_VFX_PF_MBOXX(0, 0));
     80	writeq(mbx->data, cptvf->reg_base + OTX_CPT_VFX_PF_MBOXX(0, 1));
     81}
     82
     83/* Interrupt handler to handle mailbox messages from VFs */
     84void otx_cptvf_handle_mbox_intr(struct otx_cptvf *cptvf)
     85{
     86	struct otx_cpt_mbox mbx = {};
     87
     88	/*
     89	 * MBOX[0] contains msg
     90	 * MBOX[1] contains data
     91	 */
     92	mbx.msg  = readq(cptvf->reg_base + OTX_CPT_VFX_PF_MBOXX(0, 0));
     93	mbx.data = readq(cptvf->reg_base + OTX_CPT_VFX_PF_MBOXX(0, 1));
     94
     95	dump_mbox_msg(&mbx, -1);
     96
     97	switch (mbx.msg) {
     98	case OTX_CPT_MSG_VF_UP:
     99		cptvf->pf_acked = true;
    100		cptvf->num_vfs = mbx.data;
    101		break;
    102	case OTX_CPT_MSG_READY:
    103		cptvf->pf_acked = true;
    104		cptvf->vfid = mbx.data;
    105		dev_dbg(&cptvf->pdev->dev, "Received VFID %d\n", cptvf->vfid);
    106		break;
    107	case OTX_CPT_MSG_QBIND_GRP:
    108		cptvf->pf_acked = true;
    109		cptvf->vftype = mbx.data;
    110		dev_dbg(&cptvf->pdev->dev, "VF %d type %s group %d\n",
    111			cptvf->vfid,
    112			((mbx.data == OTX_CPT_SE_TYPES) ? "SE" : "AE"),
    113			cptvf->vfgrp);
    114		break;
    115	case OTX_CPT_MSG_ACK:
    116		cptvf->pf_acked = true;
    117		break;
    118	case OTX_CPT_MSG_NACK:
    119		cptvf->pf_nacked = true;
    120		break;
    121	default:
    122		dev_err(&cptvf->pdev->dev, "Invalid msg from PF, msg 0x%llx\n",
    123			mbx.msg);
    124		break;
    125	}
    126}
    127
    128static int cptvf_send_msg_to_pf_timeout(struct otx_cptvf *cptvf,
    129					struct otx_cpt_mbox *mbx)
    130{
    131	int timeout = CPT_MBOX_MSG_TIMEOUT;
    132	int sleep = 10;
    133
    134	cptvf->pf_acked = false;
    135	cptvf->pf_nacked = false;
    136	cptvf_send_msg_to_pf(cptvf, mbx);
    137	/* Wait for previous message to be acked, timeout 2sec */
    138	while (!cptvf->pf_acked) {
    139		if (cptvf->pf_nacked)
    140			return -EINVAL;
    141		msleep(sleep);
    142		if (cptvf->pf_acked)
    143			break;
    144		timeout -= sleep;
    145		if (!timeout) {
    146			dev_err(&cptvf->pdev->dev,
    147				"PF didn't ack to mbox msg %llx from VF%u\n",
    148				mbx->msg, cptvf->vfid);
    149			return -EBUSY;
    150		}
    151	}
    152	return 0;
    153}
    154
    155/*
    156 * Checks if VF is able to comminicate with PF
    157 * and also gets the CPT number this VF is associated to.
    158 */
    159int otx_cptvf_check_pf_ready(struct otx_cptvf *cptvf)
    160{
    161	struct otx_cpt_mbox mbx = {};
    162	int ret;
    163
    164	mbx.msg = OTX_CPT_MSG_READY;
    165	ret = cptvf_send_msg_to_pf_timeout(cptvf, &mbx);
    166
    167	return ret;
    168}
    169
    170/*
    171 * Communicate VQs size to PF to program CPT(0)_PF_Q(0-15)_CTL of the VF.
    172 * Must be ACKed.
    173 */
    174int otx_cptvf_send_vq_size_msg(struct otx_cptvf *cptvf)
    175{
    176	struct otx_cpt_mbox mbx = {};
    177	int ret;
    178
    179	mbx.msg = OTX_CPT_MSG_QLEN;
    180	mbx.data = cptvf->qsize;
    181	ret = cptvf_send_msg_to_pf_timeout(cptvf, &mbx);
    182
    183	return ret;
    184}
    185
    186/*
    187 * Communicate VF group required to PF and get the VQ binded to that group
    188 */
    189int otx_cptvf_send_vf_to_grp_msg(struct otx_cptvf *cptvf, int group)
    190{
    191	struct otx_cpt_mbox mbx = {};
    192	int ret;
    193
    194	mbx.msg = OTX_CPT_MSG_QBIND_GRP;
    195	/* Convey group of the VF */
    196	mbx.data = group;
    197	ret = cptvf_send_msg_to_pf_timeout(cptvf, &mbx);
    198	if (ret)
    199		return ret;
    200	cptvf->vfgrp = group;
    201
    202	return 0;
    203}
    204
    205/*
    206 * Communicate VF group required to PF and get the VQ binded to that group
    207 */
    208int otx_cptvf_send_vf_priority_msg(struct otx_cptvf *cptvf)
    209{
    210	struct otx_cpt_mbox mbx = {};
    211	int ret;
    212
    213	mbx.msg = OTX_CPT_MSG_VQ_PRIORITY;
    214	/* Convey group of the VF */
    215	mbx.data = cptvf->priority;
    216	ret = cptvf_send_msg_to_pf_timeout(cptvf, &mbx);
    217
    218	return ret;
    219}
    220
    221/*
    222 * Communicate to PF that VF is UP and running
    223 */
    224int otx_cptvf_send_vf_up(struct otx_cptvf *cptvf)
    225{
    226	struct otx_cpt_mbox mbx = {};
    227	int ret;
    228
    229	mbx.msg = OTX_CPT_MSG_VF_UP;
    230	ret = cptvf_send_msg_to_pf_timeout(cptvf, &mbx);
    231
    232	return ret;
    233}
    234
    235/*
    236 * Communicate to PF that VF is DOWN and running
    237 */
    238int otx_cptvf_send_vf_down(struct otx_cptvf *cptvf)
    239{
    240	struct otx_cpt_mbox mbx = {};
    241	int ret;
    242
    243	mbx.msg = OTX_CPT_MSG_VF_DOWN;
    244	ret = cptvf_send_msg_to_pf_timeout(cptvf, &mbx);
    245
    246	return ret;
    247}