summaryrefslogtreecommitdiff
path: root/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto/qat/qat_common/adf_gen2_pfvf.c')
-rw-r--r--drivers/crypto/qat/qat_common/adf_gen2_pfvf.c129
1 files changed, 93 insertions, 36 deletions
diff --git a/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c b/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c
index 5ac69ece34a8..2e0b9ac27393 100644
--- a/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c
+++ b/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c
@@ -17,6 +17,14 @@
#define ADF_GEN2_PF_PF2VF_OFFSET(i) (0x3A000 + 0x280 + ((i) * 0x04))
#define ADF_GEN2_VF_PF2VF_OFFSET 0x200
+#define ADF_GEN2_CSR_IN_USE 0x6AC2
+#define ADF_GEN2_CSR_IN_USE_MASK 0xFFFE
+
+enum gen2_csr_pos {
+ ADF_GEN2_CSR_PF2VF_OFFSET = 0,
+ ADF_GEN2_CSR_VF2PF_OFFSET = 16,
+};
+
#define ADF_PFVF_MSG_ACK_DELAY 2
#define ADF_PFVF_MSG_ACK_MAX_RETRY 100
@@ -72,38 +80,81 @@ static void adf_gen2_disable_vf2pf_interrupts(void __iomem *pmisc_addr,
}
}
+static u32 gen2_csr_get_int_bit(enum gen2_csr_pos offset)
+{
+ return ADF_PFVF_INT << offset;
+}
+
+static u32 gen2_csr_msg_to_position(u32 csr_msg, enum gen2_csr_pos offset)
+{
+ return (csr_msg & 0xFFFF) << offset;
+}
+
+static u32 gen2_csr_msg_from_position(u32 csr_val, enum gen2_csr_pos offset)
+{
+ return (csr_val >> offset) & 0xFFFF;
+}
+
+static bool gen2_csr_is_in_use(u32 msg, enum gen2_csr_pos offset)
+{
+ return ((msg >> offset) & ADF_GEN2_CSR_IN_USE_MASK) == ADF_GEN2_CSR_IN_USE;
+}
+
+static void gen2_csr_clear_in_use(u32 *msg, enum gen2_csr_pos offset)
+{
+ *msg &= ~(ADF_GEN2_CSR_IN_USE_MASK << offset);
+}
+
+static void gen2_csr_set_in_use(u32 *msg, enum gen2_csr_pos offset)
+{
+ *msg |= (ADF_GEN2_CSR_IN_USE << offset);
+}
+
+static bool is_legacy_user_pfvf_message(u32 msg)
+{
+ return !(msg & ADF_PFVF_MSGORIGIN_SYSTEM);
+}
+
static int adf_gen2_pfvf_send(struct adf_accel_dev *accel_dev, u32 msg,
u8 vf_nr)
{
void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
unsigned int retries = ADF_PFVF_MSG_MAX_RETRIES;
- u32 remote_in_use_mask, remote_in_use_pattern;
- u32 local_in_use_mask, local_in_use_pattern;
- u32 val, pfvf_offset, count = 0;
+ enum gen2_csr_pos remote_offset;
+ enum gen2_csr_pos local_offset;
struct mutex *lock; /* lock preventing concurrent acces of CSR */
+ u32 pfvf_offset;
+ u32 count = 0;
u32 int_bit;
+ u32 csr_val;
int ret;
+ /* Gen2 messages, both PF->VF and VF->PF, are all 16 bits long. This
+ * allows us to build and read messages as if they where all 0 based.
+ * However, send and receive are in a single shared 32 bits register,
+ * so we need to shift and/or mask the message half before decoding
+ * it and after encoding it. Which one to shift depends on the
+ * direction.
+ */
if (accel_dev->is_vf) {
pfvf_offset = GET_PFVF_OPS(accel_dev)->get_vf2pf_offset(0);
lock = &accel_dev->vf.vf2pf_lock;
- local_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK;
- local_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF;
- remote_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK;
- remote_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF;
- int_bit = ADF_VF2PF_INT;
+ local_offset = ADF_GEN2_CSR_VF2PF_OFFSET;
+ remote_offset = ADF_GEN2_CSR_PF2VF_OFFSET;
} else {
pfvf_offset = GET_PFVF_OPS(accel_dev)->get_pf2vf_offset(vf_nr);
lock = &accel_dev->pf.vf_info[vf_nr].pf2vf_lock;
- local_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK;
- local_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF;
- remote_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK;
- remote_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF;
- int_bit = ADF_PF2VF_INT;
+ local_offset = ADF_GEN2_CSR_PF2VF_OFFSET;
+ remote_offset = ADF_GEN2_CSR_VF2PF_OFFSET;
}
- msg &= ~local_in_use_mask;
- msg |= local_in_use_pattern;
+ int_bit = gen2_csr_get_int_bit(local_offset);
+
+ /* Pre-calculate message, shifting it in place and setting
+ * the in use pattern
+ */
+ msg = gen2_csr_msg_to_position(msg, local_offset);
+ gen2_csr_set_in_use(&msg, remote_offset);
mutex_lock(lock);
@@ -111,8 +162,8 @@ start:
ret = 0;
/* Check if the PFVF CSR is in use by remote function */
- val = ADF_CSR_RD(pmisc_addr, pfvf_offset);
- if ((val & remote_in_use_mask) == remote_in_use_pattern) {
+ csr_val = ADF_CSR_RD(pmisc_addr, pfvf_offset);
+ if (gen2_csr_is_in_use(csr_val, local_offset)) {
dev_dbg(&GET_DEV(accel_dev),
"PFVF CSR in use by remote function\n");
goto retry;
@@ -124,23 +175,25 @@ start:
/* Wait for confirmation from remote func it received the message */
do {
msleep(ADF_PFVF_MSG_ACK_DELAY);
- val = ADF_CSR_RD(pmisc_addr, pfvf_offset);
- } while ((val & int_bit) && (count++ < ADF_PFVF_MSG_ACK_MAX_RETRY));
+ csr_val = ADF_CSR_RD(pmisc_addr, pfvf_offset);
+ } while ((csr_val & int_bit) && (count++ < ADF_PFVF_MSG_ACK_MAX_RETRY));
- if (val & int_bit) {
+ if (csr_val & int_bit) {
dev_dbg(&GET_DEV(accel_dev), "ACK not received from remote\n");
- val &= ~int_bit;
+ csr_val &= ~int_bit;
ret = -EIO;
}
- if (val != msg) {
+ if (csr_val != msg) {
dev_dbg(&GET_DEV(accel_dev),
"Collision - PFVF CSR overwritten by remote function\n");
goto retry;
}
/* Finished with the PFVF CSR; relinquish it and leave msg in CSR */
- ADF_CSR_WR(pmisc_addr, pfvf_offset, val & ~local_in_use_mask);
+ gen2_csr_clear_in_use(&csr_val, remote_offset);
+ ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val);
+
out:
mutex_unlock(lock);
return ret;
@@ -158,39 +211,43 @@ retry:
static u32 adf_gen2_pfvf_recv(struct adf_accel_dev *accel_dev, u8 vf_nr)
{
void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
+ enum gen2_csr_pos local_offset;
u32 pfvf_offset;
- u32 msg_origin;
u32 int_bit;
+ u32 csr_val;
u32 msg;
if (accel_dev->is_vf) {
pfvf_offset = GET_PFVF_OPS(accel_dev)->get_pf2vf_offset(0);
- int_bit = ADF_PF2VF_INT;
- msg_origin = ADF_PF2VF_MSGORIGIN_SYSTEM;
+ local_offset = ADF_GEN2_CSR_PF2VF_OFFSET;
} else {
pfvf_offset = GET_PFVF_OPS(accel_dev)->get_vf2pf_offset(vf_nr);
- int_bit = ADF_VF2PF_INT;
- msg_origin = ADF_VF2PF_MSGORIGIN_SYSTEM;
+ local_offset = ADF_GEN2_CSR_VF2PF_OFFSET;
}
+ int_bit = gen2_csr_get_int_bit(local_offset);
+
/* Read message */
- msg = ADF_CSR_RD(pmisc_addr, pfvf_offset);
- if (!(msg & int_bit)) {
+ csr_val = ADF_CSR_RD(pmisc_addr, pfvf_offset);
+ if (!(csr_val & int_bit)) {
dev_info(&GET_DEV(accel_dev),
- "Spurious PFVF interrupt, msg 0x%.8x. Ignored\n", msg);
+ "Spurious PFVF interrupt, msg 0x%.8x. Ignored\n", csr_val);
return 0;
}
- /* Ignore legacy non-system (non-kernel) VF2PF messages */
- if (!(msg & msg_origin)) {
+ /* Extract the message from the CSR */
+ msg = gen2_csr_msg_from_position(csr_val, local_offset);
+
+ /* Ignore legacy non-system (non-kernel) messages */
+ if (unlikely(is_legacy_user_pfvf_message(msg))) {
dev_dbg(&GET_DEV(accel_dev),
- "Ignored non-system message (0x%.8x);\n", msg);
+ "Ignored non-system message (0x%.8x);\n", csr_val);
return 0;
}
/* To ACK, clear the INT bit */
- msg &= ~int_bit;
- ADF_CSR_WR(pmisc_addr, pfvf_offset, msg);
+ csr_val &= ~int_bit;
+ ADF_CSR_WR(pmisc_addr, pfvf_offset, csr_val);
return msg;
}