aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/qat/qat_common/adf_pfvf_vf_msg.c
blob: 14b222691c9c2ee8ada2e6bec0ce7d79587f62cc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
/* Copyright(c) 2015 - 2021 Intel Corporation */
#include <linux/bitfield.h>
#include "adf_accel_devices.h"
#include "adf_common_drv.h"
#include "adf_pfvf_msg.h"
#include "adf_pfvf_vf_msg.h"
#include "adf_pfvf_vf_proto.h"

/**
 * adf_vf2pf_notify_init() - send init msg to PF
 * @accel_dev:  Pointer to acceleration VF device.
 *
 * Function sends an init message from the VF to a PF
 *
 * Return: 0 on success, error code otherwise.
 */
int adf_vf2pf_notify_init(struct adf_accel_dev *accel_dev)
{
	struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_INIT };

	if (adf_send_vf2pf_msg(accel_dev, msg)) {
		dev_err(&GET_DEV(accel_dev),
			"Failed to send Init event to PF\n");
		return -EFAULT;
	}
	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
	return 0;
}
EXPORT_SYMBOL_GPL(adf_vf2pf_notify_init);

/**
 * adf_vf2pf_notify_shutdown() - send shutdown msg to PF
 * @accel_dev:  Pointer to acceleration VF device.
 *
 * Function sends a shutdown message from the VF to a PF
 *
 * Return: void
 */
void adf_vf2pf_notify_shutdown(struct adf_accel_dev *accel_dev)
{
	struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_SHUTDOWN };

	if (test_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status))
		if (adf_send_vf2pf_msg(accel_dev, msg))
			dev_err(&GET_DEV(accel_dev),
				"Failed to send Shutdown event to PF\n");
}
EXPORT_SYMBOL_GPL(adf_vf2pf_notify_shutdown);

int adf_vf2pf_request_version(struct adf_accel_dev *accel_dev)
{
	u8 pf_version;
	int compat;
	int ret;
	struct pfvf_message resp;
	struct pfvf_message msg = {
		.type = ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ,
		.data = ADF_PFVF_COMPAT_THIS_VERSION,
	};

	BUILD_BUG_ON(ADF_PFVF_COMPAT_THIS_VERSION > 255);

	ret = adf_send_vf2pf_req(accel_dev, msg, &resp);
	if (ret) {
		dev_err(&GET_DEV(accel_dev),
			"Failed to send Compatibility Version Request.\n");
		return ret;
	}

	pf_version = FIELD_GET(ADF_PF2VF_VERSION_RESP_VERS_MASK, resp.data);
	compat = FIELD_GET(ADF_PF2VF_VERSION_RESP_RESULT_MASK, resp.data);

	/* Response from PF received, check compatibility */
	switch (compat) {
	case ADF_PF2VF_VF_COMPATIBLE:
		break;
	case ADF_PF2VF_VF_COMPAT_UNKNOWN:
		/* VF is newer than PF - compatible for now */
		break;
	case ADF_PF2VF_VF_INCOMPATIBLE:
		dev_err(&GET_DEV(accel_dev),
			"PF (vers %d) and VF (vers %d) are not compatible\n",
			pf_version, ADF_PFVF_COMPAT_THIS_VERSION);
		return -EINVAL;
	default:
		dev_err(&GET_DEV(accel_dev),
			"Invalid response from PF; assume not compatible\n");
		return -EINVAL;
	}

	accel_dev->vf.pf_compat_ver = pf_version;
	return 0;
}

int adf_vf2pf_get_capabilities(struct adf_accel_dev *accel_dev)
{
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	struct capabilities_v3 cap_msg = { { 0 }, };
	unsigned int len = sizeof(cap_msg);

	if (accel_dev->vf.pf_compat_ver < ADF_PFVF_COMPAT_CAPABILITIES)
		/* The PF is too old to support the extended capabilities */
		return 0;

	if (adf_send_vf2pf_blkmsg_req(accel_dev, ADF_VF2PF_BLKMSG_REQ_CAP_SUMMARY,
				      (u8 *)&cap_msg, &len)) {
		dev_err(&GET_DEV(accel_dev),
			"QAT: Failed to get block message response\n");
		return -EFAULT;
	}

	switch (cap_msg.hdr.version) {
	default:
		/* Newer version received, handle only the know parts */
		fallthrough;
	case ADF_PFVF_CAPABILITIES_V3_VERSION:
		if (likely(len >= sizeof(struct capabilities_v3)))
			hw_data->clock_frequency = cap_msg.frequency;
		else
			dev_info(&GET_DEV(accel_dev), "Could not get frequency");
		fallthrough;
	case ADF_PFVF_CAPABILITIES_V2_VERSION:
		if (likely(len >= sizeof(struct capabilities_v2)))
			hw_data->accel_capabilities_mask = cap_msg.capabilities;
		else
			dev_info(&GET_DEV(accel_dev), "Could not get capabilities");
		fallthrough;
	case ADF_PFVF_CAPABILITIES_V1_VERSION:
		if (likely(len >= sizeof(struct capabilities_v1))) {
			hw_data->extended_dc_capabilities = cap_msg.ext_dc_caps;
		} else {
			dev_err(&GET_DEV(accel_dev),
				"Capabilities message truncated to %d bytes\n", len);
			return -EFAULT;
		}
	}

	return 0;
}

int adf_vf2pf_get_ring_to_svc(struct adf_accel_dev *accel_dev)
{
	struct ring_to_svc_map_v1 rts_map_msg = { { 0 }, };
	unsigned int len = sizeof(rts_map_msg);

	if (accel_dev->vf.pf_compat_ver < ADF_PFVF_COMPAT_RING_TO_SVC_MAP)
		/* Use already set default mappings */
		return 0;

	if (adf_send_vf2pf_blkmsg_req(accel_dev, ADF_VF2PF_BLKMSG_REQ_RING_SVC_MAP,
				      (u8 *)&rts_map_msg, &len)) {
		dev_err(&GET_DEV(accel_dev),
			"QAT: Failed to get block message response\n");
		return -EFAULT;
	}

	if (unlikely(len < sizeof(struct ring_to_svc_map_v1))) {
		dev_err(&GET_DEV(accel_dev),
			"RING_TO_SVC message truncated to %d bytes\n", len);
		return -EFAULT;
	}

	/* Only v1 at present */
	accel_dev->hw_device->ring_to_svc_map = rts_map_msg.map;
	return 0;
}