cptvf_mbox.c (4389B)
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}