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