brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · 1267e1e Raw
192 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 msg24	 * MBOX[1] contains data25	 */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 PF87 * 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 group124 */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 group143 */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 running161 */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 running178 */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}192