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