| 1 | // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) |
| 2 | /* Copyright(c) 2015 - 2021 Intel Corporation */ |
| 3 | #include <linux/delay.h> |
| 4 | #include <linux/pci.h> |
| 5 | #include "adf_accel_devices.h" |
| 6 | #include "adf_pfvf_msg.h" |
| 7 | #include "adf_pfvf_pf_msg.h" |
| 8 | #include "adf_pfvf_pf_proto.h" |
| 9 | |
| 10 | #define ADF_PF_WAIT_RESTARTING_COMPLETE_DELAY 100 |
| 11 | #define ADF_VF_SHUTDOWN_RETRY 100 |
| 12 | |
| 13 | void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev) |
| 14 | { |
| 15 | struct adf_accel_vf_info *vf; |
| 16 | struct pfvf_message msg = { .type = ADF_PF2VF_MSGTYPE_RESTARTING }; |
| 17 | int i, num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev)); |
| 18 | |
| 19 | dev_dbg(&GET_DEV(accel_dev), "pf2vf notify restarting\n" ); |
| 20 | for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) { |
| 21 | if (vf->init && vf->vf_compat_ver >= ADF_PFVF_COMPAT_FALLBACK) |
| 22 | vf->restarting = true; |
| 23 | else |
| 24 | vf->restarting = false; |
| 25 | |
| 26 | if (!vf->init) |
| 27 | continue; |
| 28 | |
| 29 | if (adf_send_pf2vf_msg(accel_dev, vf_nr: i, msg)) |
| 30 | dev_err(&GET_DEV(accel_dev), |
| 31 | "Failed to send restarting msg to VF%d\n" , i); |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | void adf_pf2vf_wait_for_restarting_complete(struct adf_accel_dev *accel_dev) |
| 36 | { |
| 37 | int num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev)); |
| 38 | int i, retries = ADF_VF_SHUTDOWN_RETRY; |
| 39 | struct adf_accel_vf_info *vf; |
| 40 | bool vf_running; |
| 41 | |
| 42 | dev_dbg(&GET_DEV(accel_dev), "pf2vf wait for restarting complete\n" ); |
| 43 | do { |
| 44 | vf_running = false; |
| 45 | for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) |
| 46 | if (vf->restarting) |
| 47 | vf_running = true; |
| 48 | if (!vf_running) |
| 49 | break; |
| 50 | msleep(ADF_PF_WAIT_RESTARTING_COMPLETE_DELAY); |
| 51 | } while (--retries); |
| 52 | |
| 53 | if (vf_running) |
| 54 | dev_warn(&GET_DEV(accel_dev), "Some VFs are still running\n" ); |
| 55 | } |
| 56 | |
| 57 | void adf_pf2vf_notify_restarted(struct adf_accel_dev *accel_dev) |
| 58 | { |
| 59 | struct pfvf_message msg = { .type = ADF_PF2VF_MSGTYPE_RESTARTED }; |
| 60 | int i, num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev)); |
| 61 | struct adf_accel_vf_info *vf; |
| 62 | |
| 63 | dev_dbg(&GET_DEV(accel_dev), "pf2vf notify restarted\n" ); |
| 64 | for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) { |
| 65 | if (vf->init && vf->vf_compat_ver >= ADF_PFVF_COMPAT_FALLBACK && |
| 66 | adf_send_pf2vf_msg(accel_dev, vf_nr: i, msg)) |
| 67 | dev_err(&GET_DEV(accel_dev), |
| 68 | "Failed to send restarted msg to VF%d\n" , i); |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | void adf_pf2vf_notify_fatal_error(struct adf_accel_dev *accel_dev) |
| 73 | { |
| 74 | struct pfvf_message msg = { .type = ADF_PF2VF_MSGTYPE_FATAL_ERROR }; |
| 75 | int i, num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev)); |
| 76 | struct adf_accel_vf_info *vf; |
| 77 | |
| 78 | dev_dbg(&GET_DEV(accel_dev), "pf2vf notify fatal error\n" ); |
| 79 | for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) { |
| 80 | if (vf->init && vf->vf_compat_ver >= ADF_PFVF_COMPAT_FALLBACK && |
| 81 | adf_send_pf2vf_msg(accel_dev, vf_nr: i, msg)) |
| 82 | dev_err(&GET_DEV(accel_dev), |
| 83 | "Failed to send fatal error msg to VF%d\n" , i); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | int adf_pf_capabilities_msg_provider(struct adf_accel_dev *accel_dev, |
| 88 | u8 *buffer, u8 compat) |
| 89 | { |
| 90 | struct adf_hw_device_data *hw_data = accel_dev->hw_device; |
| 91 | struct capabilities_v2 caps_msg; |
| 92 | |
| 93 | caps_msg.ext_dc_caps = hw_data->extended_dc_capabilities; |
| 94 | caps_msg.capabilities = hw_data->accel_capabilities_mask; |
| 95 | |
| 96 | caps_msg.hdr.version = ADF_PFVF_CAPABILITIES_V2_VERSION; |
| 97 | caps_msg.hdr.payload_size = |
| 98 | ADF_PFVF_BLKMSG_PAYLOAD_SIZE(struct capabilities_v2); |
| 99 | |
| 100 | memcpy(buffer, &caps_msg, sizeof(caps_msg)); |
| 101 | |
| 102 | return 0; |
| 103 | } |
| 104 | |
| 105 | int adf_pf_ring_to_svc_msg_provider(struct adf_accel_dev *accel_dev, |
| 106 | u8 *buffer, u8 compat) |
| 107 | { |
| 108 | struct ring_to_svc_map_v1 rts_map_msg; |
| 109 | |
| 110 | rts_map_msg.map = accel_dev->hw_device->ring_to_svc_map; |
| 111 | rts_map_msg.hdr.version = ADF_PFVF_RING_TO_SVC_VERSION; |
| 112 | rts_map_msg.hdr.payload_size = ADF_PFVF_BLKMSG_PAYLOAD_SIZE(rts_map_msg); |
| 113 | |
| 114 | memcpy(buffer, &rts_map_msg, sizeof(rts_map_msg)); |
| 115 | |
| 116 | return 0; |
| 117 | } |
| 118 | |