File Index
Files and directories
Sign in
FILE

cptvf_mbox.c

File preview with syntax highlighting.

linux-6.19.14/drivers/crypto/cavium/cpt/cptvf_mbox.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2016 Cavium, Inc.
  4 */
  5
  6#include "cptvf.h"
  7
  8static void cptvf_send_msg_to_pf(struct cpt_vf *cptvf, struct cpt_mbox *mbx)
  9{
 10	/* Writing mbox(1) causes interrupt */
 11	cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0),
 12			mbx->msg);
 13	cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1),
 14			mbx->data);
 15}
 16
 17/* Interrupt handler to handle mailbox messages from VFs */
 18void cptvf_handle_mbox_intr(struct cpt_vf *cptvf)
 19{
 20	struct cpt_mbox mbx = {};
 21
 22	/*
 23	 * MBOX[0] contains msg
 24	 * MBOX[1] contains data
 25	 */
 26	mbx.msg  = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0));
 27	mbx.data = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1));
 28	dev_dbg(&cptvf->pdev->dev, "%s: Mailbox msg 0x%llx from PF\n",
 29		__func__, mbx.msg);
 30	switch (mbx.msg) {
 31	case CPT_MSG_READY:
 32	{
 33		cptvf->pf_acked = true;
 34		cptvf->vfid = mbx.data;
 35		dev_dbg(&cptvf->pdev->dev, "Received VFID %d\n", cptvf->vfid);
 36		break;
 37	}
 38	case CPT_MSG_QBIND_GRP:
 39		cptvf->pf_acked = true;
 40		cptvf->vftype = mbx.data;
 41		dev_dbg(&cptvf->pdev->dev, "VF %d type %s group %d\n",
 42			cptvf->vfid, ((mbx.data == SE_TYPES) ? "SE" : "AE"),
 43			cptvf->vfgrp);
 44		break;
 45	case CPT_MBOX_MSG_TYPE_ACK:
 46		cptvf->pf_acked = true;
 47		break;
 48	case CPT_MBOX_MSG_TYPE_NACK:
 49		cptvf->pf_nacked = true;
 50		break;
 51	default:
 52		dev_err(&cptvf->pdev->dev, "Invalid msg from PF, msg 0x%llx\n",
 53			mbx.msg);
 54		break;
 55	}
 56}
 57
 58static int cptvf_send_msg_to_pf_timeout(struct cpt_vf *cptvf,
 59					struct cpt_mbox *mbx)
 60{
 61	int timeout = CPT_MBOX_MSG_TIMEOUT;
 62	int sleep = 10;
 63
 64	cptvf->pf_acked = false;
 65	cptvf->pf_nacked = false;
 66	cptvf_send_msg_to_pf(cptvf, mbx);
 67	/* Wait for previous message to be acked, timeout 2sec */
 68	while (!cptvf->pf_acked) {
 69		if (cptvf->pf_nacked)
 70			return -EINVAL;
 71		msleep(sleep);
 72		if (cptvf->pf_acked)
 73			break;
 74		timeout -= sleep;
 75		if (!timeout) {
 76			dev_err(&cptvf->pdev->dev, "PF didn't ack to mbox msg %llx from VF%u\n",
 77				(mbx->msg & 0xFF), cptvf->vfid);
 78			return -EBUSY;
 79		}
 80	}
 81
 82	return 0;
 83}
 84
 85/*
 86 * Checks if VF is able to comminicate with PF
 87 * and also gets the CPT number this VF is associated to.
 88 */
 89int cptvf_check_pf_ready(struct cpt_vf *cptvf)
 90{
 91	struct pci_dev *pdev = cptvf->pdev;
 92	struct cpt_mbox mbx = {};
 93
 94	mbx.msg = CPT_MSG_READY;
 95	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
 96		dev_err(&pdev->dev, "PF didn't respond to READY msg\n");
 97		return -EBUSY;
 98	}
 99
100	return 0;
101}
102
103/*
104 * Communicate VQs size to PF to program CPT(0)_PF_Q(0-15)_CTL of the VF.
105 * Must be ACKed.
106 */
107int cptvf_send_vq_size_msg(struct cpt_vf *cptvf)
108{
109	struct pci_dev *pdev = cptvf->pdev;
110	struct cpt_mbox mbx = {};
111
112	mbx.msg = CPT_MSG_QLEN;
113	mbx.data = cptvf->qsize;
114	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
115		dev_err(&pdev->dev, "PF didn't respond to vq_size msg\n");
116		return -EBUSY;
117	}
118
119	return 0;
120}
121
122/*
123 * Communicate VF group required to PF and get the VQ binded to that group
124 */
125int cptvf_send_vf_to_grp_msg(struct cpt_vf *cptvf)
126{
127	struct pci_dev *pdev = cptvf->pdev;
128	struct cpt_mbox mbx = {};
129
130	mbx.msg = CPT_MSG_QBIND_GRP;
131	/* Convey group of the VF */
132	mbx.data = cptvf->vfgrp;
133	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
134		dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n");
135		return -EBUSY;
136	}
137
138	return 0;
139}
140
141/*
142 * Communicate VF group required to PF and get the VQ binded to that group
143 */
144int cptvf_send_vf_priority_msg(struct cpt_vf *cptvf)
145{
146	struct pci_dev *pdev = cptvf->pdev;
147	struct cpt_mbox mbx = {};
148
149	mbx.msg = CPT_MSG_VQ_PRIORITY;
150	/* Convey group of the VF */
151	mbx.data = cptvf->priority;
152	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
153		dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n");
154		return -EBUSY;
155	}
156	return 0;
157}
158
159/*
160 * Communicate to PF that VF is UP and running
161 */
162int cptvf_send_vf_up(struct cpt_vf *cptvf)
163{
164	struct pci_dev *pdev = cptvf->pdev;
165	struct cpt_mbox mbx = {};
166
167	mbx.msg = CPT_MSG_VF_UP;
168	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
169		dev_err(&pdev->dev, "PF didn't respond to UP msg\n");
170		return -EBUSY;
171	}
172
173	return 0;
174}
175
176/*
177 * Communicate to PF that VF is DOWN and running
178 */
179int cptvf_send_vf_down(struct cpt_vf *cptvf)
180{
181	struct pci_dev *pdev = cptvf->pdev;
182	struct cpt_mbox mbx = {};
183
184	mbx.msg = CPT_MSG_VF_DOWN;
185	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
186		dev_err(&pdev->dev, "PF didn't respond to DOWN msg\n");
187		return -EBUSY;
188	}
189
190	return 0;
191}
~/ Read-only file preview.