1*cf718eaaSSrikanth, Jampala // SPDX-License-Identifier: GPL-2.0 2*cf718eaaSSrikanth, Jampala #include <linux/workqueue.h> 3*cf718eaaSSrikanth, Jampala 4*cf718eaaSSrikanth, Jampala #include "nitrox_csr.h" 5*cf718eaaSSrikanth, Jampala #include "nitrox_hal.h" 6*cf718eaaSSrikanth, Jampala #include "nitrox_dev.h" 7*cf718eaaSSrikanth, Jampala 8*cf718eaaSSrikanth, Jampala #define RING_TO_VFNO(_x, _y) ((_x) / (_y)) 9*cf718eaaSSrikanth, Jampala 10*cf718eaaSSrikanth, Jampala /** 11*cf718eaaSSrikanth, Jampala * mbx_msg_type - Mailbox message types 12*cf718eaaSSrikanth, Jampala */ 13*cf718eaaSSrikanth, Jampala enum mbx_msg_type { 14*cf718eaaSSrikanth, Jampala MBX_MSG_TYPE_NOP, 15*cf718eaaSSrikanth, Jampala MBX_MSG_TYPE_REQ, 16*cf718eaaSSrikanth, Jampala MBX_MSG_TYPE_ACK, 17*cf718eaaSSrikanth, Jampala MBX_MSG_TYPE_NACK, 18*cf718eaaSSrikanth, Jampala }; 19*cf718eaaSSrikanth, Jampala 20*cf718eaaSSrikanth, Jampala /** 21*cf718eaaSSrikanth, Jampala * mbx_msg_opcode - Mailbox message opcodes 22*cf718eaaSSrikanth, Jampala */ 23*cf718eaaSSrikanth, Jampala enum mbx_msg_opcode { 24*cf718eaaSSrikanth, Jampala MSG_OP_VF_MODE = 1, 25*cf718eaaSSrikanth, Jampala MSG_OP_VF_UP, 26*cf718eaaSSrikanth, Jampala MSG_OP_VF_DOWN, 27*cf718eaaSSrikanth, Jampala MSG_OP_CHIPID_VFID, 28*cf718eaaSSrikanth, Jampala }; 29*cf718eaaSSrikanth, Jampala 30*cf718eaaSSrikanth, Jampala struct pf2vf_work { 31*cf718eaaSSrikanth, Jampala struct nitrox_vfdev *vfdev; 32*cf718eaaSSrikanth, Jampala struct nitrox_device *ndev; 33*cf718eaaSSrikanth, Jampala struct work_struct pf2vf_resp; 34*cf718eaaSSrikanth, Jampala }; 35*cf718eaaSSrikanth, Jampala 36*cf718eaaSSrikanth, Jampala static inline u64 pf2vf_read_mbox(struct nitrox_device *ndev, int ring) 37*cf718eaaSSrikanth, Jampala { 38*cf718eaaSSrikanth, Jampala u64 reg_addr; 39*cf718eaaSSrikanth, Jampala 40*cf718eaaSSrikanth, Jampala reg_addr = NPS_PKT_MBOX_VF_PF_PFDATAX(ring); 41*cf718eaaSSrikanth, Jampala return nitrox_read_csr(ndev, reg_addr); 42*cf718eaaSSrikanth, Jampala } 43*cf718eaaSSrikanth, Jampala 44*cf718eaaSSrikanth, Jampala static inline void pf2vf_write_mbox(struct nitrox_device *ndev, u64 value, 45*cf718eaaSSrikanth, Jampala int ring) 46*cf718eaaSSrikanth, Jampala { 47*cf718eaaSSrikanth, Jampala u64 reg_addr; 48*cf718eaaSSrikanth, Jampala 49*cf718eaaSSrikanth, Jampala reg_addr = NPS_PKT_MBOX_PF_VF_PFDATAX(ring); 50*cf718eaaSSrikanth, Jampala nitrox_write_csr(ndev, reg_addr, value); 51*cf718eaaSSrikanth, Jampala } 52*cf718eaaSSrikanth, Jampala 53*cf718eaaSSrikanth, Jampala static void pf2vf_send_response(struct nitrox_device *ndev, 54*cf718eaaSSrikanth, Jampala struct nitrox_vfdev *vfdev) 55*cf718eaaSSrikanth, Jampala { 56*cf718eaaSSrikanth, Jampala union mbox_msg msg; 57*cf718eaaSSrikanth, Jampala 58*cf718eaaSSrikanth, Jampala msg.value = vfdev->msg.value; 59*cf718eaaSSrikanth, Jampala 60*cf718eaaSSrikanth, Jampala switch (vfdev->msg.opcode) { 61*cf718eaaSSrikanth, Jampala case MSG_OP_VF_MODE: 62*cf718eaaSSrikanth, Jampala msg.data = ndev->mode; 63*cf718eaaSSrikanth, Jampala break; 64*cf718eaaSSrikanth, Jampala case MSG_OP_VF_UP: 65*cf718eaaSSrikanth, Jampala vfdev->nr_queues = vfdev->msg.data; 66*cf718eaaSSrikanth, Jampala atomic_set(&vfdev->state, __NDEV_READY); 67*cf718eaaSSrikanth, Jampala break; 68*cf718eaaSSrikanth, Jampala case MSG_OP_CHIPID_VFID: 69*cf718eaaSSrikanth, Jampala msg.id.chipid = ndev->idx; 70*cf718eaaSSrikanth, Jampala msg.id.vfid = vfdev->vfno; 71*cf718eaaSSrikanth, Jampala break; 72*cf718eaaSSrikanth, Jampala case MSG_OP_VF_DOWN: 73*cf718eaaSSrikanth, Jampala vfdev->nr_queues = 0; 74*cf718eaaSSrikanth, Jampala atomic_set(&vfdev->state, __NDEV_NOT_READY); 75*cf718eaaSSrikanth, Jampala break; 76*cf718eaaSSrikanth, Jampala default: 77*cf718eaaSSrikanth, Jampala msg.type = MBX_MSG_TYPE_NOP; 78*cf718eaaSSrikanth, Jampala break; 79*cf718eaaSSrikanth, Jampala } 80*cf718eaaSSrikanth, Jampala 81*cf718eaaSSrikanth, Jampala if (msg.type == MBX_MSG_TYPE_NOP) 82*cf718eaaSSrikanth, Jampala return; 83*cf718eaaSSrikanth, Jampala 84*cf718eaaSSrikanth, Jampala /* send ACK to VF */ 85*cf718eaaSSrikanth, Jampala msg.type = MBX_MSG_TYPE_ACK; 86*cf718eaaSSrikanth, Jampala pf2vf_write_mbox(ndev, msg.value, vfdev->ring); 87*cf718eaaSSrikanth, Jampala 88*cf718eaaSSrikanth, Jampala vfdev->msg.value = 0; 89*cf718eaaSSrikanth, Jampala atomic64_inc(&vfdev->mbx_resp); 90*cf718eaaSSrikanth, Jampala } 91*cf718eaaSSrikanth, Jampala 92*cf718eaaSSrikanth, Jampala static void pf2vf_resp_handler(struct work_struct *work) 93*cf718eaaSSrikanth, Jampala { 94*cf718eaaSSrikanth, Jampala struct pf2vf_work *pf2vf_resp = container_of(work, struct pf2vf_work, 95*cf718eaaSSrikanth, Jampala pf2vf_resp); 96*cf718eaaSSrikanth, Jampala struct nitrox_vfdev *vfdev = pf2vf_resp->vfdev; 97*cf718eaaSSrikanth, Jampala struct nitrox_device *ndev = pf2vf_resp->ndev; 98*cf718eaaSSrikanth, Jampala 99*cf718eaaSSrikanth, Jampala switch (vfdev->msg.type) { 100*cf718eaaSSrikanth, Jampala case MBX_MSG_TYPE_REQ: 101*cf718eaaSSrikanth, Jampala /* process the request from VF */ 102*cf718eaaSSrikanth, Jampala pf2vf_send_response(ndev, vfdev); 103*cf718eaaSSrikanth, Jampala break; 104*cf718eaaSSrikanth, Jampala case MBX_MSG_TYPE_ACK: 105*cf718eaaSSrikanth, Jampala case MBX_MSG_TYPE_NACK: 106*cf718eaaSSrikanth, Jampala break; 107*cf718eaaSSrikanth, Jampala }; 108*cf718eaaSSrikanth, Jampala 109*cf718eaaSSrikanth, Jampala kfree(pf2vf_resp); 110*cf718eaaSSrikanth, Jampala } 111*cf718eaaSSrikanth, Jampala 112*cf718eaaSSrikanth, Jampala void nitrox_pf2vf_mbox_handler(struct nitrox_device *ndev) 113*cf718eaaSSrikanth, Jampala { 114*cf718eaaSSrikanth, Jampala struct nitrox_vfdev *vfdev; 115*cf718eaaSSrikanth, Jampala struct pf2vf_work *pfwork; 116*cf718eaaSSrikanth, Jampala u64 value, reg_addr; 117*cf718eaaSSrikanth, Jampala u32 i; 118*cf718eaaSSrikanth, Jampala int vfno; 119*cf718eaaSSrikanth, Jampala 120*cf718eaaSSrikanth, Jampala /* loop for VF(0..63) */ 121*cf718eaaSSrikanth, Jampala reg_addr = NPS_PKT_MBOX_INT_LO; 122*cf718eaaSSrikanth, Jampala value = nitrox_read_csr(ndev, reg_addr); 123*cf718eaaSSrikanth, Jampala for_each_set_bit(i, (const unsigned long *)&value, BITS_PER_LONG) { 124*cf718eaaSSrikanth, Jampala /* get the vfno from ring */ 125*cf718eaaSSrikanth, Jampala vfno = RING_TO_VFNO(i, ndev->iov.max_vf_queues); 126*cf718eaaSSrikanth, Jampala vfdev = ndev->iov.vfdev + vfno; 127*cf718eaaSSrikanth, Jampala vfdev->ring = i; 128*cf718eaaSSrikanth, Jampala /* fill the vf mailbox data */ 129*cf718eaaSSrikanth, Jampala vfdev->msg.value = pf2vf_read_mbox(ndev, vfdev->ring); 130*cf718eaaSSrikanth, Jampala pfwork = kzalloc(sizeof(*pfwork), GFP_ATOMIC); 131*cf718eaaSSrikanth, Jampala if (!pfwork) 132*cf718eaaSSrikanth, Jampala continue; 133*cf718eaaSSrikanth, Jampala 134*cf718eaaSSrikanth, Jampala pfwork->vfdev = vfdev; 135*cf718eaaSSrikanth, Jampala pfwork->ndev = ndev; 136*cf718eaaSSrikanth, Jampala INIT_WORK(&pfwork->pf2vf_resp, pf2vf_resp_handler); 137*cf718eaaSSrikanth, Jampala queue_work(ndev->iov.pf2vf_wq, &pfwork->pf2vf_resp); 138*cf718eaaSSrikanth, Jampala /* clear the corresponding vf bit */ 139*cf718eaaSSrikanth, Jampala nitrox_write_csr(ndev, reg_addr, BIT_ULL(i)); 140*cf718eaaSSrikanth, Jampala } 141*cf718eaaSSrikanth, Jampala 142*cf718eaaSSrikanth, Jampala /* loop for VF(64..127) */ 143*cf718eaaSSrikanth, Jampala reg_addr = NPS_PKT_MBOX_INT_HI; 144*cf718eaaSSrikanth, Jampala value = nitrox_read_csr(ndev, reg_addr); 145*cf718eaaSSrikanth, Jampala for_each_set_bit(i, (const unsigned long *)&value, BITS_PER_LONG) { 146*cf718eaaSSrikanth, Jampala /* get the vfno from ring */ 147*cf718eaaSSrikanth, Jampala vfno = RING_TO_VFNO(i + 64, ndev->iov.max_vf_queues); 148*cf718eaaSSrikanth, Jampala vfdev = ndev->iov.vfdev + vfno; 149*cf718eaaSSrikanth, Jampala vfdev->ring = (i + 64); 150*cf718eaaSSrikanth, Jampala /* fill the vf mailbox data */ 151*cf718eaaSSrikanth, Jampala vfdev->msg.value = pf2vf_read_mbox(ndev, vfdev->ring); 152*cf718eaaSSrikanth, Jampala 153*cf718eaaSSrikanth, Jampala pfwork = kzalloc(sizeof(*pfwork), GFP_ATOMIC); 154*cf718eaaSSrikanth, Jampala if (!pfwork) 155*cf718eaaSSrikanth, Jampala continue; 156*cf718eaaSSrikanth, Jampala 157*cf718eaaSSrikanth, Jampala pfwork->vfdev = vfdev; 158*cf718eaaSSrikanth, Jampala pfwork->ndev = ndev; 159*cf718eaaSSrikanth, Jampala INIT_WORK(&pfwork->pf2vf_resp, pf2vf_resp_handler); 160*cf718eaaSSrikanth, Jampala queue_work(ndev->iov.pf2vf_wq, &pfwork->pf2vf_resp); 161*cf718eaaSSrikanth, Jampala /* clear the corresponding vf bit */ 162*cf718eaaSSrikanth, Jampala nitrox_write_csr(ndev, reg_addr, BIT_ULL(i)); 163*cf718eaaSSrikanth, Jampala } 164*cf718eaaSSrikanth, Jampala } 165*cf718eaaSSrikanth, Jampala 166*cf718eaaSSrikanth, Jampala int nitrox_mbox_init(struct nitrox_device *ndev) 167*cf718eaaSSrikanth, Jampala { 168*cf718eaaSSrikanth, Jampala struct nitrox_vfdev *vfdev; 169*cf718eaaSSrikanth, Jampala int i; 170*cf718eaaSSrikanth, Jampala 171*cf718eaaSSrikanth, Jampala ndev->iov.vfdev = kcalloc(ndev->iov.num_vfs, 172*cf718eaaSSrikanth, Jampala sizeof(struct nitrox_vfdev), GFP_KERNEL); 173*cf718eaaSSrikanth, Jampala if (!ndev->iov.vfdev) 174*cf718eaaSSrikanth, Jampala return -ENOMEM; 175*cf718eaaSSrikanth, Jampala 176*cf718eaaSSrikanth, Jampala for (i = 0; i < ndev->iov.num_vfs; i++) { 177*cf718eaaSSrikanth, Jampala vfdev = ndev->iov.vfdev + i; 178*cf718eaaSSrikanth, Jampala vfdev->vfno = i; 179*cf718eaaSSrikanth, Jampala } 180*cf718eaaSSrikanth, Jampala 181*cf718eaaSSrikanth, Jampala /* allocate pf2vf response workqueue */ 182*cf718eaaSSrikanth, Jampala ndev->iov.pf2vf_wq = alloc_workqueue("nitrox_pf2vf", 0, 0); 183*cf718eaaSSrikanth, Jampala if (!ndev->iov.pf2vf_wq) { 184*cf718eaaSSrikanth, Jampala kfree(ndev->iov.vfdev); 185*cf718eaaSSrikanth, Jampala return -ENOMEM; 186*cf718eaaSSrikanth, Jampala } 187*cf718eaaSSrikanth, Jampala /* enable pf2vf mailbox interrupts */ 188*cf718eaaSSrikanth, Jampala enable_pf2vf_mbox_interrupts(ndev); 189*cf718eaaSSrikanth, Jampala 190*cf718eaaSSrikanth, Jampala return 0; 191*cf718eaaSSrikanth, Jampala } 192*cf718eaaSSrikanth, Jampala 193*cf718eaaSSrikanth, Jampala void nitrox_mbox_cleanup(struct nitrox_device *ndev) 194*cf718eaaSSrikanth, Jampala { 195*cf718eaaSSrikanth, Jampala /* disable pf2vf mailbox interrupts */ 196*cf718eaaSSrikanth, Jampala disable_pf2vf_mbox_interrupts(ndev); 197*cf718eaaSSrikanth, Jampala /* destroy workqueue */ 198*cf718eaaSSrikanth, Jampala if (ndev->iov.pf2vf_wq) 199*cf718eaaSSrikanth, Jampala destroy_workqueue(ndev->iov.pf2vf_wq); 200*cf718eaaSSrikanth, Jampala 201*cf718eaaSSrikanth, Jampala kfree(ndev->iov.vfdev); 202*cf718eaaSSrikanth, Jampala ndev->iov.pf2vf_wq = NULL; 203*cf718eaaSSrikanth, Jampala ndev->iov.vfdev = NULL; 204*cf718eaaSSrikanth, Jampala } 205