FILE
adf_gen4_pfvf.c
File preview with syntax highlighting.
linux-6.19.14/drivers/crypto/intel/qat/qat_common/adf_gen4_pfvf.c
1// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) 2/* Copyright(c) 2021 Intel Corporation */ 3#include <linux/iopoll.h> 4#include <linux/mutex.h> 5#include <linux/types.h> 6#include "adf_accel_devices.h" 7#include "adf_common_drv.h" 8#include "adf_gen4_pfvf.h" 9#include "adf_gen4_hw_data.h" 10#include "adf_pfvf_pf_proto.h" 11#include "adf_pfvf_utils.h" 12 13/* VF2PF interrupt source registers */ 14#define ADF_4XXX_VM2PF_SOU 0x41A180 15#define ADF_4XXX_VM2PF_MSK 0x41A1C0 16#define ADF_GEN4_VF_MSK 0xFFFF 17 18#define ADF_PFVF_GEN4_MSGTYPE_SHIFT 2 19#define ADF_PFVF_GEN4_MSGTYPE_MASK 0x3F 20#define ADF_PFVF_GEN4_MSGDATA_SHIFT 8 21#define ADF_PFVF_GEN4_MSGDATA_MASK 0xFFFFFF 22 23static const struct pfvf_csr_format csr_gen4_fmt = { 24 { ADF_PFVF_GEN4_MSGTYPE_SHIFT, ADF_PFVF_GEN4_MSGTYPE_MASK }, 25 { ADF_PFVF_GEN4_MSGDATA_SHIFT, ADF_PFVF_GEN4_MSGDATA_MASK }, 26}; 27 28static u32 adf_gen4_pf_get_pf2vf_offset(u32 i) 29{ 30 return ADF_GEN4_PF2VM_OFFSET(i); 31} 32 33static u32 adf_gen4_pf_get_vf2pf_offset(u32 i) 34{ 35 return ADF_GEN4_VM2PF_OFFSET(i); 36} 37 38static void adf_gen4_enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask) 39{ 40 u32 val; 41 42 val = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK) & ~vf_mask; 43 ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, val); 44} 45 46static void adf_gen4_disable_all_vf2pf_interrupts(void __iomem *pmisc_addr) 47{ 48 ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, ADF_GEN4_VF_MSK); 49} 50 51static u32 adf_gen4_disable_pending_vf2pf_interrupts(void __iomem *pmisc_addr) 52{ 53 u32 sources, disabled, pending; 54 55 /* Get the interrupt sources triggered by VFs */ 56 sources = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_SOU); 57 if (!sources) 58 return 0; 59 60 /* Get the already disabled interrupts */ 61 disabled = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK); 62 63 pending = sources & ~disabled; 64 if (!pending) 65 return 0; 66 67 /* Due to HW limitations, when disabling the interrupts, we can't 68 * just disable the requested sources, as this would lead to missed 69 * interrupts if VM2PF_SOU changes just before writing to VM2PF_MSK. 70 * To work around it, disable all and re-enable only the sources that 71 * are not in vf_mask and were not already disabled. Re-enabling will 72 * trigger a new interrupt for the sources that have changed in the 73 * meantime, if any. 74 */ 75 ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, ADF_GEN4_VF_MSK); 76 ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, disabled | sources); 77 78 /* Return the sources of the (new) interrupt(s) */ 79 return pending; 80} 81 82static int adf_gen4_pfvf_send(struct adf_accel_dev *accel_dev, 83 struct pfvf_message msg, u32 pfvf_offset, 84 struct mutex *csr_lock) 85{ 86 void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev); 87 u32 csr_val; 88 int ret; 89 90 csr_val = adf_pfvf_csr_msg_of(accel_dev, msg, &csr_gen4_fmt); 91 if (unlikely(!csr_val)) 92 return -EINVAL; 93 94 mutex_lock(csr_lock); 95 96 ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val | ADF_PFVF_INT); 97 98 /* Wait for confirmation from remote that it received the message */ 99 ret = read_poll_timeout(ADF_CSR_RD, csr_val, !(csr_val & ADF_PFVF_INT), 100 ADF_PFVF_MSG_ACK_DELAY_US, 101 ADF_PFVF_MSG_ACK_MAX_DELAY_US, 102 true, pmisc_addr, pfvf_offset); 103 if (ret < 0) 104 dev_dbg(&GET_DEV(accel_dev), "ACK not received from remote\n"); 105 106 mutex_unlock(csr_lock); 107 return ret; 108} 109 110static struct pfvf_message adf_gen4_pfvf_recv(struct adf_accel_dev *accel_dev, 111 u32 pfvf_offset, u8 compat_ver) 112{ 113 void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev); 114 struct pfvf_message msg = { 0 }; 115 u32 csr_val; 116 117 /* Read message from the CSR */ 118 csr_val = ADF_CSR_RD(pmisc_addr, pfvf_offset); 119 if (!(csr_val & ADF_PFVF_INT)) { 120 dev_info(&GET_DEV(accel_dev), 121 "Spurious PFVF interrupt, msg 0x%.8x. Ignored\n", csr_val); 122 return msg; 123 } 124 125 /* We can now acknowledge the message reception by clearing the 126 * interrupt bit 127 */ 128 ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val & ~ADF_PFVF_INT); 129 130 /* Return the pfvf_message format */ 131 return adf_pfvf_message_of(accel_dev, csr_val, &csr_gen4_fmt); 132} 133 134void adf_gen4_init_pf_pfvf_ops(struct adf_pfvf_ops *pfvf_ops) 135{ 136 pfvf_ops->enable_comms = adf_enable_pf2vf_comms; 137 pfvf_ops->get_pf2vf_offset = adf_gen4_pf_get_pf2vf_offset; 138 pfvf_ops->get_vf2pf_offset = adf_gen4_pf_get_vf2pf_offset; 139 pfvf_ops->enable_vf2pf_interrupts = adf_gen4_enable_vf2pf_interrupts; 140 pfvf_ops->disable_all_vf2pf_interrupts = adf_gen4_disable_all_vf2pf_interrupts; 141 pfvf_ops->disable_pending_vf2pf_interrupts = adf_gen4_disable_pending_vf2pf_interrupts; 142 pfvf_ops->send_msg = adf_gen4_pfvf_send; 143 pfvf_ops->recv_msg = adf_gen4_pfvf_recv; 144} 145EXPORT_SYMBOL_GPL(adf_gen4_init_pf_pfvf_ops);
~/
Read-only file preview.