1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright(c) 2007-2022 Intel Corporation */ 3 /* $FreeBSD$ */ 4 #include <linux/bitfield.h> 5 #include "adf_accel_devices.h" 6 #include "adf_common_drv.h" 7 #include "adf_pfvf_msg.h" 8 #include "adf_pfvf_vf_msg.h" 9 #include "adf_pfvf_vf_proto.h" 10 11 /** 12 * adf_vf2pf_notify_init() - send init msg to PF 13 * @accel_dev: Pointer to acceleration VF device. 14 * 15 * Function sends an init message from the VF to a PF 16 * 17 * Return: 0 on success, error code otherwise. 18 */ 19 int 20 adf_vf2pf_notify_init(struct adf_accel_dev *accel_dev) 21 { 22 struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_INIT }; 23 24 if (adf_send_vf2pf_msg(accel_dev, msg)) { 25 device_printf(GET_DEV(accel_dev), 26 "Failed to send Init event to PF\n"); 27 return -EFAULT; 28 } 29 set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); 30 return 0; 31 } 32 33 /** 34 * adf_vf2pf_notify_shutdown() - send shutdown msg to PF 35 * @accel_dev: Pointer to acceleration VF device. 36 * 37 * Function sends a shutdown message from the VF to a PF 38 * 39 * Return: void 40 */ 41 void 42 adf_vf2pf_notify_shutdown(struct adf_accel_dev *accel_dev) 43 { 44 struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_SHUTDOWN }; 45 46 if (test_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status)) 47 if (adf_send_vf2pf_msg(accel_dev, msg)) 48 device_printf(GET_DEV(accel_dev), 49 "Failed to send Shutdown event to PF\n"); 50 } 51 52 int 53 adf_vf2pf_request_version(struct adf_accel_dev *accel_dev) 54 { 55 u8 pf_version; 56 int compat; 57 int ret; 58 struct pfvf_message resp; 59 struct pfvf_message msg = { 60 .type = ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ, 61 .data = ADF_PFVF_COMPAT_THIS_VERSION, 62 }; 63 64 BUILD_BUG_ON(ADF_PFVF_COMPAT_THIS_VERSION > 255); 65 66 ret = adf_send_vf2pf_req(accel_dev, msg, &resp); 67 if (ret) { 68 device_printf( 69 GET_DEV(accel_dev), 70 "Failed to send Compatibility Version Request.\n"); 71 return ret; 72 } 73 74 pf_version = FIELD_GET(ADF_PF2VF_VERSION_RESP_VERS_MASK, resp.data); 75 compat = FIELD_GET(ADF_PF2VF_VERSION_RESP_RESULT_MASK, resp.data); 76 77 /* Response from PF received, check compatibility */ 78 switch (compat) { 79 case ADF_PF2VF_VF_COMPATIBLE: 80 break; 81 case ADF_PF2VF_VF_COMPAT_UNKNOWN: 82 /* VF is newer than PF - compatible for now */ 83 break; 84 case ADF_PF2VF_VF_INCOMPATIBLE: 85 device_printf( 86 GET_DEV(accel_dev), 87 "PF (vers %d) and VF (vers %d) are not compatible\n", 88 pf_version, 89 ADF_PFVF_COMPAT_THIS_VERSION); 90 return -EINVAL; 91 default: 92 device_printf( 93 GET_DEV(accel_dev), 94 "Invalid response from PF; assume not compatible\n"); 95 return -EINVAL; 96 } 97 98 accel_dev->u1.vf.pf_compat_ver = pf_version; 99 return 0; 100 } 101 102 int 103 adf_vf2pf_get_capabilities(struct adf_accel_dev *accel_dev) 104 { 105 struct adf_hw_device_data *hw_data = accel_dev->hw_device; 106 struct capabilities_v3 cap_msg = { 0 }; 107 unsigned int len = sizeof(cap_msg); 108 109 if (accel_dev->u1.vf.pf_compat_ver < ADF_PFVF_COMPAT_CAPABILITIES) 110 /* The PF is too old to support the extended capabilities */ 111 return 0; 112 113 if (adf_send_vf2pf_blkmsg_req(accel_dev, 114 ADF_VF2PF_BLKMSG_REQ_CAP_SUMMARY, 115 (u8 *)&cap_msg, 116 &len)) { 117 device_printf(GET_DEV(accel_dev), 118 "QAT: Failed to get block message response\n"); 119 return -EFAULT; 120 } 121 122 switch (cap_msg.hdr.version) { 123 default: 124 /* Newer version received, handle only the know parts */ 125 fallthrough; 126 case ADF_PFVF_CAPABILITIES_V3_VERSION: 127 if (likely(len >= sizeof(struct capabilities_v3))) 128 hw_data->clock_frequency = cap_msg.frequency; 129 else 130 device_printf(GET_DEV(accel_dev), 131 "Could not get frequency"); 132 fallthrough; 133 case ADF_PFVF_CAPABILITIES_V2_VERSION: 134 if (likely(len >= sizeof(struct capabilities_v2))) { 135 hw_data->accel_capabilities_mask = cap_msg.capabilities; 136 } else { 137 device_printf(GET_DEV(accel_dev), 138 "Could not get capabilities"); 139 } 140 fallthrough; 141 case ADF_PFVF_CAPABILITIES_V1_VERSION: 142 if (likely(len >= sizeof(struct capabilities_v1))) { 143 hw_data->extended_dc_capabilities = cap_msg.ext_dc_caps; 144 } else { 145 device_printf( 146 GET_DEV(accel_dev), 147 "Capabilities message truncated to %d bytes\n", 148 len); 149 return -EFAULT; 150 } 151 } 152 153 return 0; 154 } 155 156 int 157 adf_vf2pf_get_ring_to_svc(struct adf_accel_dev *accel_dev) 158 { 159 struct ring_to_svc_map_v1 rts_map_msg = { 0 }; 160 unsigned int len = sizeof(rts_map_msg); 161 162 if (accel_dev->u1.vf.pf_compat_ver < ADF_PFVF_COMPAT_RING_TO_SVC_MAP) 163 /* Use already set default mappings */ 164 return 0; 165 166 if (adf_send_vf2pf_blkmsg_req(accel_dev, 167 ADF_VF2PF_BLKMSG_REQ_RING_SVC_MAP, 168 (u8 *)&rts_map_msg, 169 &len)) { 170 device_printf(GET_DEV(accel_dev), 171 "QAT: Failed to get block message response\n"); 172 return -EFAULT; 173 } 174 175 if (unlikely(len < sizeof(struct ring_to_svc_map_v1))) { 176 device_printf(GET_DEV(accel_dev), 177 "RING_TO_SVC message truncated to %d bytes\n", 178 len); 179 return -EFAULT; 180 } 181 182 /* Only v1 at present */ 183 accel_dev->hw_device->ring_to_svc_map = rts_map_msg.map; 184 return 0; 185 } 186