2020-05-27 15:21:28 +00:00
|
|
|
// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
|
2021-11-17 14:30:51 +00:00
|
|
|
/* Copyright(c) 2015 - 2021 Intel Corporation */
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/types.h>
|
2015-08-07 18:34:25 +00:00
|
|
|
#include "adf_accel_devices.h"
|
|
|
|
#include "adf_common_drv.h"
|
2021-11-17 14:30:51 +00:00
|
|
|
#include "adf_pfvf_msg.h"
|
|
|
|
#include "adf_pfvf_pf_proto.h"
|
2021-09-28 11:44:36 +00:00
|
|
|
|
2021-09-28 11:44:38 +00:00
|
|
|
/**
|
|
|
|
* adf_send_pf2vf_msg() - send PF to VF message
|
|
|
|
* @accel_dev: Pointer to acceleration device
|
|
|
|
* @vf_nr: VF number to which the message will be sent
|
|
|
|
* @msg: Message to send
|
|
|
|
*
|
|
|
|
* This function allows the PF to send a message to a specific VF.
|
|
|
|
*
|
|
|
|
* Return: 0 on success, error code otherwise.
|
|
|
|
*/
|
2021-11-17 14:30:51 +00:00
|
|
|
int adf_send_pf2vf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr, u32 msg)
|
2021-09-28 11:44:38 +00:00
|
|
|
{
|
2021-12-16 09:13:18 +00:00
|
|
|
struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
|
|
|
|
u32 pfvf_offset = pfvf_ops->get_pf2vf_offset(vf_nr);
|
|
|
|
|
|
|
|
return pfvf_ops->send_msg(accel_dev, msg, pfvf_offset,
|
|
|
|
&accel_dev->pf.vf_info[vf_nr].pf2vf_lock);
|
2021-09-28 11:44:38 +00:00
|
|
|
}
|
|
|
|
|
2021-11-17 14:30:50 +00:00
|
|
|
/**
|
|
|
|
* adf_recv_vf2pf_msg() - receive a VF to PF message
|
|
|
|
* @accel_dev: Pointer to acceleration device
|
|
|
|
* @vf_nr: Number of the VF from where the message will be received
|
|
|
|
*
|
|
|
|
* This function allows the PF to receive a message from a specific VF.
|
|
|
|
*
|
|
|
|
* Return: a valid message on success, zero otherwise.
|
|
|
|
*/
|
|
|
|
static u32 adf_recv_vf2pf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr)
|
|
|
|
{
|
2021-12-16 09:13:18 +00:00
|
|
|
struct adf_pfvf_ops *pfvf_ops = GET_PFVF_OPS(accel_dev);
|
|
|
|
u32 pfvf_offset = pfvf_ops->get_vf2pf_offset(vf_nr);
|
|
|
|
|
|
|
|
return pfvf_ops->recv_msg(accel_dev, pfvf_offset);
|
2021-11-17 14:30:50 +00:00
|
|
|
}
|
|
|
|
|
2021-11-17 14:30:42 +00:00
|
|
|
static int adf_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u32 vf_nr,
|
|
|
|
u32 msg, u32 *response)
|
2015-08-24 18:56:02 +00:00
|
|
|
{
|
2021-11-17 14:30:39 +00:00
|
|
|
struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr];
|
2021-11-17 14:30:42 +00:00
|
|
|
u32 resp = 0;
|
2021-11-17 14:30:40 +00:00
|
|
|
|
2021-12-16 09:13:17 +00:00
|
|
|
switch ((msg >> ADF_PFVF_MSGTYPE_SHIFT) & ADF_PFVF_MSGTYPE_MASK) {
|
2015-08-24 18:56:02 +00:00
|
|
|
case ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ:
|
|
|
|
{
|
|
|
|
u8 vf_compat_ver = msg >> ADF_VF2PF_COMPAT_VER_REQ_SHIFT;
|
2021-11-17 14:30:55 +00:00
|
|
|
u8 compat;
|
2015-08-24 18:56:02 +00:00
|
|
|
|
|
|
|
dev_dbg(&GET_DEV(accel_dev),
|
2021-11-17 14:30:58 +00:00
|
|
|
"VersionRequest received from VF%d (vers %d) to PF (vers %d)\n",
|
|
|
|
vf_nr, vf_compat_ver, ADF_PFVF_COMPAT_THIS_VERSION);
|
2015-08-24 18:56:02 +00:00
|
|
|
|
2021-11-17 14:30:58 +00:00
|
|
|
if (vf_compat_ver <= ADF_PFVF_COMPAT_THIS_VERSION)
|
2021-11-17 14:30:56 +00:00
|
|
|
compat = ADF_PF2VF_VF_COMPATIBLE;
|
2021-11-17 14:30:58 +00:00
|
|
|
else
|
2021-11-17 14:30:56 +00:00
|
|
|
compat = ADF_PF2VF_VF_COMPAT_UNKNOWN;
|
2021-11-17 14:30:55 +00:00
|
|
|
|
|
|
|
resp |= ADF_PF2VF_MSGTYPE_VERSION_RESP <<
|
2021-12-16 09:13:17 +00:00
|
|
|
ADF_PFVF_MSGTYPE_SHIFT;
|
2021-11-17 14:30:55 +00:00
|
|
|
resp |= ADF_PFVF_COMPAT_THIS_VERSION <<
|
|
|
|
ADF_PF2VF_VERSION_RESP_VERS_SHIFT;
|
|
|
|
resp |= compat << ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
|
2015-08-24 18:56:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ADF_VF2PF_MSGTYPE_VERSION_REQ:
|
2021-11-17 14:30:55 +00:00
|
|
|
{
|
|
|
|
u8 compat;
|
|
|
|
|
2015-08-24 18:56:02 +00:00
|
|
|
dev_dbg(&GET_DEV(accel_dev),
|
2021-11-17 14:30:58 +00:00
|
|
|
"Legacy VersionRequest received from VF%d to PF (vers 1.1)\n",
|
|
|
|
vf_nr);
|
2021-11-17 14:30:55 +00:00
|
|
|
|
|
|
|
/* PF always newer than legacy VF */
|
|
|
|
compat = ADF_PF2VF_VF_COMPATIBLE;
|
|
|
|
|
|
|
|
resp |= ADF_PF2VF_MSGTYPE_VERSION_RESP <<
|
2021-12-16 09:13:17 +00:00
|
|
|
ADF_PFVF_MSGTYPE_SHIFT;
|
2015-08-24 18:56:02 +00:00
|
|
|
/* Set legacy major and minor version num */
|
|
|
|
resp |= 1 << ADF_PF2VF_MAJORVERSION_SHIFT |
|
|
|
|
1 << ADF_PF2VF_MINORVERSION_SHIFT;
|
2021-11-17 14:30:55 +00:00
|
|
|
resp |= compat << ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
|
|
|
|
}
|
2015-08-24 18:56:02 +00:00
|
|
|
break;
|
|
|
|
case ADF_VF2PF_MSGTYPE_INIT:
|
|
|
|
{
|
|
|
|
dev_dbg(&GET_DEV(accel_dev),
|
2021-11-17 14:30:58 +00:00
|
|
|
"Init message received from VF%d\n", vf_nr);
|
2015-08-24 18:56:02 +00:00
|
|
|
vf_info->init = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ADF_VF2PF_MSGTYPE_SHUTDOWN:
|
|
|
|
{
|
|
|
|
dev_dbg(&GET_DEV(accel_dev),
|
2021-11-17 14:30:58 +00:00
|
|
|
"Shutdown message received from VF%d\n", vf_nr);
|
2015-08-24 18:56:02 +00:00
|
|
|
vf_info->init = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2021-11-17 14:30:58 +00:00
|
|
|
dev_dbg(&GET_DEV(accel_dev), "Unknown message from VF%d (0x%.8x)\n",
|
2021-11-17 14:30:57 +00:00
|
|
|
vf_nr, msg);
|
2021-11-17 14:30:42 +00:00
|
|
|
return -ENOMSG;
|
|
|
|
}
|
|
|
|
|
|
|
|
*response = resp;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool adf_recv_and_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u32 vf_nr)
|
|
|
|
{
|
2021-11-17 14:30:50 +00:00
|
|
|
u32 resp = 0;
|
|
|
|
u32 msg;
|
2021-11-17 14:30:42 +00:00
|
|
|
|
2021-11-17 14:30:50 +00:00
|
|
|
msg = adf_recv_vf2pf_msg(accel_dev, vf_nr);
|
|
|
|
if (!msg)
|
2021-11-17 14:30:42 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (adf_handle_vf2pf_msg(accel_dev, vf_nr, msg, &resp))
|
|
|
|
return false;
|
|
|
|
|
2021-09-28 11:44:38 +00:00
|
|
|
if (resp && adf_send_pf2vf_msg(accel_dev, vf_nr, resp))
|
2021-11-17 14:30:58 +00:00
|
|
|
dev_err(&GET_DEV(accel_dev),
|
|
|
|
"Failed to send response to VF%d\n", vf_nr);
|
2015-08-24 18:56:02 +00:00
|
|
|
|
2021-11-17 14:30:39 +00:00
|
|
|
return true;
|
2015-08-24 18:56:02 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 11:44:40 +00:00
|
|
|
/**
|
|
|
|
* adf_enable_pf2vf_comms() - Function enables communication from pf to vf
|
|
|
|
*
|
|
|
|
* @accel_dev: Pointer to acceleration device virtual function.
|
|
|
|
*
|
|
|
|
* This function carries out the necessary steps to setup and start the PFVF
|
|
|
|
* communication channel, if any.
|
|
|
|
*
|
|
|
|
* Return: 0 on success, error code otherwise.
|
|
|
|
*/
|
|
|
|
int adf_enable_pf2vf_comms(struct adf_accel_dev *accel_dev)
|
|
|
|
{
|
|
|
|
spin_lock_init(&accel_dev->pf.vf2pf_ints_lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(adf_enable_pf2vf_comms);
|