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