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