get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/90381/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 90381,
    "url": "http://patches.dpdk.org/api/patches/90381/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20210401123817.14348-9-ndabilpuram@marvell.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20210401123817.14348-9-ndabilpuram@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210401123817.14348-9-ndabilpuram@marvell.com",
    "date": "2021-04-01T12:37:33",
    "name": "[v3,08/52] common/cnxk: add VF support to base device class",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "38cb069ac0ad152322fdcaba1183ab507e3e5df5",
    "submitter": {
        "id": 1202,
        "url": "http://patches.dpdk.org/api/people/1202/?format=api",
        "name": "Nithin Dabilpuram",
        "email": "ndabilpuram@marvell.com"
    },
    "delegate": {
        "id": 310,
        "url": "http://patches.dpdk.org/api/users/310/?format=api",
        "username": "jerin",
        "first_name": "Jerin",
        "last_name": "Jacob",
        "email": "jerinj@marvell.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20210401123817.14348-9-ndabilpuram@marvell.com/mbox/",
    "series": [
        {
            "id": 16059,
            "url": "http://patches.dpdk.org/api/series/16059/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=16059",
            "date": "2021-04-01T12:37:25",
            "name": "Add Marvell CNXK common driver",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/16059/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/90381/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/90381/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 5F775A0548;\n\tThu,  1 Apr 2021 14:40:11 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 515B11411BE;\n\tThu,  1 Apr 2021 14:39:04 +0200 (CEST)",
            "from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com\n [67.231.148.174])\n by mails.dpdk.org (Postfix) with ESMTP id 0899F1411C4\n for <dev@dpdk.org>; Thu,  1 Apr 2021 14:39:01 +0200 (CEST)",
            "from pps.filterd (m0045849.ppops.net [127.0.0.1])\n by mx0a-0016f401.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id\n 131CPNX4032520 for <dev@dpdk.org>; Thu, 1 Apr 2021 05:39:01 -0700",
            "from dc5-exch01.marvell.com ([199.233.59.181])\n by mx0a-0016f401.pphosted.com with ESMTP id 37n28j2dpf-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT)\n for <dev@dpdk.org>; Thu, 01 Apr 2021 05:39:01 -0700",
            "from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com\n (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.2;\n Thu, 1 Apr 2021 05:38:59 -0700",
            "from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.2 via Frontend\n Transport; Thu, 1 Apr 2021 05:38:59 -0700",
            "from hyd1588t430.marvell.com (unknown [10.29.52.204])\n by maili.marvell.com (Postfix) with ESMTP id 25AC43F703F;\n Thu,  1 Apr 2021 05:38:56 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;\n h=from : to : cc :\n subject : date : message-id : in-reply-to : references : mime-version :\n content-type; s=pfpt0220; bh=SWTWTeQcss6Df8piJEhZg7xwngs0bcHjw0LzIBgQDxw=;\n b=QAFKoaPUVUitZv0Li1nbdLTEK/e+r+9Xj+QAlkA5qdHpfNQ99la+DG5zhs1noOvCQuEr\n AWLlP1LIm4EpHxU0ByVIudnAB255Hmc5/9P9wljNUyLQo+VkI0Q1emedr6Yr+1het5UQ\n pEsgUluioJi+iuO89poz98tlgLUwNO5f555AchyqEoX0VogXVSQtVONDVc8nKjAbHhrd\n WPQl1McWzjvRkV6ab+ELwVN3aCJjzIekCzYmSlnUqTW48cSxTR8LhJw1WxcwDhy85NhB\n aFQWfgBaqUDaT7ZgIRDBoenc3B8y/o+4NcX99HVsPqnsDEAM9n2lKAf96u0DONuXWz1h MA==",
        "From": "Nithin Dabilpuram <ndabilpuram@marvell.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<jerinj@marvell.com>, <skori@marvell.com>, <skoteshwar@marvell.com>,\n <pbhagavatula@marvell.com>, <kirankumark@marvell.com>,\n <psatheesh@marvell.com>, <asekhar@marvell.com>",
        "Date": "Thu, 1 Apr 2021 18:07:33 +0530",
        "Message-ID": "<20210401123817.14348-9-ndabilpuram@marvell.com>",
        "X-Mailer": "git-send-email 2.8.4",
        "In-Reply-To": "<20210401123817.14348-1-ndabilpuram@marvell.com>",
        "References": "<20210305133918.8005-1-ndabilpuram@marvell.com>\n <20210401123817.14348-1-ndabilpuram@marvell.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Proofpoint-ORIG-GUID": "dk0ZSltgWU3r8-JrE8yzEhBIhSugw2BA",
        "X-Proofpoint-GUID": "dk0ZSltgWU3r8-JrE8yzEhBIhSugw2BA",
        "X-Proofpoint-Virus-Version": "vendor=fsecure engine=2.50.10434:6.0.369, 18.0.761\n definitions=2021-04-01_05:2021-03-31,\n 2021-04-01 signatures=0",
        "Subject": "[dpdk-dev] [PATCH v3 08/52] common/cnxk: add VF support to base\n device class",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Jerin Jacob <jerinj@marvell.com>\n\nAdd VF specific handling such as BAR4 setup, forwarding\nVF mbox messages to AF and vice-versa, VF FLR handling\netc.\n\nSigned-off-by: Jerin Jacob <jerinj@marvell.com>\n---\n drivers/common/cnxk/roc_dev.c      | 857 ++++++++++++++++++++++++++++++++++++-\n drivers/common/cnxk/roc_dev_priv.h |  42 ++\n 2 files changed, 879 insertions(+), 20 deletions(-)",
    "diff": "diff --git a/drivers/common/cnxk/roc_dev.c b/drivers/common/cnxk/roc_dev.c\nindex 380c71b..4cd5978 100644\n--- a/drivers/common/cnxk/roc_dev.c\n+++ b/drivers/common/cnxk/roc_dev.c\n@@ -17,6 +17,337 @@\n /* Single Root I/O Virtualization */\n #define ROC_PCI_SRIOV_TOTAL_VF 0x0e /* Total VFs */\n \n+static void *\n+mbox_mem_map(off_t off, size_t size)\n+{\n+\tvoid *va = MAP_FAILED;\n+\tint mem_fd;\n+\n+\tif (size <= 0 || !off) {\n+\t\tplt_err(\"Invalid mbox area off 0x%lx size %lu\", off, size);\n+\t\tgoto error;\n+\t}\n+\n+\tmem_fd = open(\"/dev/mem\", O_RDWR);\n+\tif (mem_fd < 0)\n+\t\tgoto error;\n+\n+\tva = plt_mmap(NULL, size, PLT_PROT_READ | PLT_PROT_WRITE,\n+\t\t      PLT_MAP_SHARED, mem_fd, off);\n+\tclose(mem_fd);\n+\n+\tif (va == MAP_FAILED)\n+\t\tplt_err(\"Failed to mmap sz=0x%zx, fd=%d, off=%jd\", size, mem_fd,\n+\t\t\t(intmax_t)off);\n+error:\n+\treturn va;\n+}\n+\n+static void\n+mbox_mem_unmap(void *va, size_t size)\n+{\n+\tif (va)\n+\t\tmunmap(va, size);\n+}\n+\n+static int\n+pf_af_sync_msg(struct dev *dev, struct mbox_msghdr **rsp)\n+{\n+\tuint32_t timeout = 0, sleep = 1;\n+\tstruct mbox *mbox = dev->mbox;\n+\tstruct mbox_dev *mdev = &mbox->dev[0];\n+\n+\tvolatile uint64_t int_status;\n+\tstruct mbox_msghdr *msghdr;\n+\tuint64_t off;\n+\tint rc = 0;\n+\n+\t/* We need to disable PF interrupts. We are in timer interrupt */\n+\tplt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);\n+\n+\t/* Send message */\n+\tmbox_msg_send(mbox, 0);\n+\n+\tdo {\n+\t\tplt_delay_ms(sleep);\n+\t\ttimeout += sleep;\n+\t\tif (timeout >= mbox->rsp_tmo) {\n+\t\t\tplt_err(\"Message timeout: %dms\", mbox->rsp_tmo);\n+\t\t\trc = -EIO;\n+\t\t\tbreak;\n+\t\t}\n+\t\tint_status = plt_read64(dev->bar2 + RVU_PF_INT);\n+\t} while ((int_status & 0x1) != 0x1);\n+\n+\t/* Clear */\n+\tplt_write64(int_status, dev->bar2 + RVU_PF_INT);\n+\n+\t/* Enable interrupts */\n+\tplt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1S);\n+\n+\tif (rc == 0) {\n+\t\t/* Get message */\n+\t\toff = mbox->rx_start +\n+\t\t      PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);\n+\t\tmsghdr = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + off);\n+\t\tif (rsp)\n+\t\t\t*rsp = msghdr;\n+\t\trc = msghdr->rc;\n+\t}\n+\n+\treturn rc;\n+}\n+\n+static int\n+af_pf_wait_msg(struct dev *dev, uint16_t vf, int num_msg)\n+{\n+\tuint32_t timeout = 0, sleep = 1;\n+\tstruct mbox *mbox = dev->mbox;\n+\tstruct mbox_dev *mdev = &mbox->dev[0];\n+\tvolatile uint64_t int_status;\n+\tstruct mbox_hdr *req_hdr;\n+\tstruct mbox_msghdr *msg;\n+\tstruct mbox_msghdr *rsp;\n+\tuint64_t offset;\n+\tsize_t size;\n+\tint i;\n+\n+\t/* We need to disable PF interrupts. We are in timer interrupt */\n+\tplt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);\n+\n+\t/* Send message */\n+\tmbox_msg_send(mbox, 0);\n+\n+\tdo {\n+\t\tplt_delay_ms(sleep);\n+\t\ttimeout++;\n+\t\tif (timeout >= mbox->rsp_tmo) {\n+\t\t\tplt_err(\"Routed messages %d timeout: %dms\", num_msg,\n+\t\t\t\tmbox->rsp_tmo);\n+\t\t\tbreak;\n+\t\t}\n+\t\tint_status = plt_read64(dev->bar2 + RVU_PF_INT);\n+\t} while ((int_status & 0x1) != 0x1);\n+\n+\t/* Clear */\n+\tplt_write64(~0ull, dev->bar2 + RVU_PF_INT);\n+\n+\t/* Enable interrupts */\n+\tplt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1S);\n+\n+\tplt_spinlock_lock(&mdev->mbox_lock);\n+\n+\treq_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);\n+\tif (req_hdr->num_msgs != num_msg)\n+\t\tplt_err(\"Routed messages: %d received: %d\", num_msg,\n+\t\t\treq_hdr->num_msgs);\n+\n+\t/* Get messages from mbox */\n+\toffset = mbox->rx_start +\n+\t\t PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);\n+\tfor (i = 0; i < req_hdr->num_msgs; i++) {\n+\t\tmsg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);\n+\t\tsize = mbox->rx_start + msg->next_msgoff - offset;\n+\n+\t\t/* Reserve PF/VF mbox message */\n+\t\tsize = PLT_ALIGN(size, MBOX_MSG_ALIGN);\n+\t\trsp = mbox_alloc_msg(&dev->mbox_vfpf, vf, size);\n+\t\tmbox_rsp_init(msg->id, rsp);\n+\n+\t\t/* Copy message from AF<->PF mbox to PF<->VF mbox */\n+\t\tmbox_memcpy((uint8_t *)rsp + sizeof(struct mbox_msghdr),\n+\t\t\t    (uint8_t *)msg + sizeof(struct mbox_msghdr),\n+\t\t\t    size - sizeof(struct mbox_msghdr));\n+\n+\t\t/* Set status and sender pf_func data */\n+\t\trsp->rc = msg->rc;\n+\t\trsp->pcifunc = msg->pcifunc;\n+\n+\t\toffset = mbox->rx_start + msg->next_msgoff;\n+\t}\n+\tplt_spinlock_unlock(&mdev->mbox_lock);\n+\n+\treturn req_hdr->num_msgs;\n+}\n+\n+static int\n+vf_pf_process_msgs(struct dev *dev, uint16_t vf)\n+{\n+\tstruct mbox *mbox = &dev->mbox_vfpf;\n+\tstruct mbox_dev *mdev = &mbox->dev[vf];\n+\tstruct mbox_hdr *req_hdr;\n+\tstruct mbox_msghdr *msg;\n+\tint offset, routed = 0;\n+\tsize_t size;\n+\tuint16_t i;\n+\n+\treq_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);\n+\tif (!req_hdr->num_msgs)\n+\t\treturn 0;\n+\n+\toffset = mbox->rx_start + PLT_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);\n+\n+\tfor (i = 0; i < req_hdr->num_msgs; i++) {\n+\t\tmsg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);\n+\t\tsize = mbox->rx_start + msg->next_msgoff - offset;\n+\n+\t\t/* RVU_PF_FUNC_S */\n+\t\tmsg->pcifunc = dev_pf_func(dev->pf, vf);\n+\n+\t\tif (msg->id == MBOX_MSG_READY) {\n+\t\t\tstruct ready_msg_rsp *rsp;\n+\t\t\tuint16_t max_bits = sizeof(dev->active_vfs[0]) * 8;\n+\n+\t\t\t/* Handle READY message in PF */\n+\t\t\tdev->active_vfs[vf / max_bits] |=\n+\t\t\t\tBIT_ULL(vf % max_bits);\n+\t\t\trsp = (struct ready_msg_rsp *)mbox_alloc_msg(\n+\t\t\t\tmbox, vf, sizeof(*rsp));\n+\t\t\tmbox_rsp_init(msg->id, rsp);\n+\n+\t\t\t/* PF/VF function ID */\n+\t\t\trsp->hdr.pcifunc = msg->pcifunc;\n+\t\t\trsp->hdr.rc = 0;\n+\t\t} else {\n+\t\t\tstruct mbox_msghdr *af_req;\n+\t\t\t/* Reserve AF/PF mbox message */\n+\t\t\tsize = PLT_ALIGN(size, MBOX_MSG_ALIGN);\n+\t\t\taf_req = mbox_alloc_msg(dev->mbox, 0, size);\n+\t\t\tif (af_req == NULL)\n+\t\t\t\treturn -ENOSPC;\n+\t\t\tmbox_req_init(msg->id, af_req);\n+\n+\t\t\t/* Copy message from VF<->PF mbox to PF<->AF mbox */\n+\t\t\tmbox_memcpy((uint8_t *)af_req +\n+\t\t\t\t\t    sizeof(struct mbox_msghdr),\n+\t\t\t\t    (uint8_t *)msg + sizeof(struct mbox_msghdr),\n+\t\t\t\t    size - sizeof(struct mbox_msghdr));\n+\t\t\taf_req->pcifunc = msg->pcifunc;\n+\t\t\trouted++;\n+\t\t}\n+\t\toffset = mbox->rx_start + msg->next_msgoff;\n+\t}\n+\n+\tif (routed > 0) {\n+\t\tplt_base_dbg(\"pf:%d routed %d messages from vf:%d to AF\",\n+\t\t\t     dev->pf, routed, vf);\n+\t\taf_pf_wait_msg(dev, vf, routed);\n+\t\tmbox_reset(dev->mbox, 0);\n+\t}\n+\n+\t/* Send mbox responses to VF */\n+\tif (mdev->num_msgs) {\n+\t\tplt_base_dbg(\"pf:%d reply %d messages to vf:%d\", dev->pf,\n+\t\t\t     mdev->num_msgs, vf);\n+\t\tmbox_msg_send(mbox, vf);\n+\t}\n+\n+\treturn i;\n+}\n+\n+static int\n+vf_pf_process_up_msgs(struct dev *dev, uint16_t vf)\n+{\n+\tstruct mbox *mbox = &dev->mbox_vfpf_up;\n+\tstruct mbox_dev *mdev = &mbox->dev[vf];\n+\tstruct mbox_hdr *req_hdr;\n+\tstruct mbox_msghdr *msg;\n+\tint msgs_acked = 0;\n+\tint offset;\n+\tuint16_t i;\n+\n+\treq_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);\n+\tif (req_hdr->num_msgs == 0)\n+\t\treturn 0;\n+\n+\toffset = mbox->rx_start + PLT_ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);\n+\n+\tfor (i = 0; i < req_hdr->num_msgs; i++) {\n+\t\tmsg = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);\n+\n+\t\tmsgs_acked++;\n+\t\t/* RVU_PF_FUNC_S */\n+\t\tmsg->pcifunc = dev_pf_func(dev->pf, vf);\n+\n+\t\tswitch (msg->id) {\n+\t\tcase MBOX_MSG_CGX_LINK_EVENT:\n+\t\t\tplt_base_dbg(\"PF: Msg 0x%x (%s) fn:0x%x (pf:%d,vf:%d)\",\n+\t\t\t\t     msg->id, mbox_id2name(msg->id),\n+\t\t\t\t     msg->pcifunc, dev_get_pf(msg->pcifunc),\n+\t\t\t\t     dev_get_vf(msg->pcifunc));\n+\t\t\tbreak;\n+\t\tcase MBOX_MSG_CGX_PTP_RX_INFO:\n+\t\t\tplt_base_dbg(\"PF: Msg 0x%x (%s) fn:0x%x (pf:%d,vf:%d)\",\n+\t\t\t\t     msg->id, mbox_id2name(msg->id),\n+\t\t\t\t     msg->pcifunc, dev_get_pf(msg->pcifunc),\n+\t\t\t\t     dev_get_vf(msg->pcifunc));\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tplt_err(\"Not handled UP msg 0x%x (%s) func:0x%x\",\n+\t\t\t\tmsg->id, mbox_id2name(msg->id), msg->pcifunc);\n+\t\t}\n+\t\toffset = mbox->rx_start + msg->next_msgoff;\n+\t}\n+\tmbox_reset(mbox, vf);\n+\tmdev->msgs_acked = msgs_acked;\n+\tplt_wmb();\n+\n+\treturn i;\n+}\n+\n+static void\n+roc_vf_pf_mbox_handle_msg(void *param)\n+{\n+\tuint16_t vf, max_vf, max_bits;\n+\tstruct dev *dev = param;\n+\n+\tmax_bits = sizeof(dev->intr.bits[0]) * sizeof(uint64_t);\n+\tmax_vf = max_bits * MAX_VFPF_DWORD_BITS;\n+\n+\tfor (vf = 0; vf < max_vf; vf++) {\n+\t\tif (dev->intr.bits[vf / max_bits] & BIT_ULL(vf % max_bits)) {\n+\t\t\tplt_base_dbg(\"Process vf:%d request (pf:%d, vf:%d)\", vf,\n+\t\t\t\t     dev->pf, dev->vf);\n+\t\t\tvf_pf_process_msgs(dev, vf);\n+\t\t\t/* UP messages */\n+\t\t\tvf_pf_process_up_msgs(dev, vf);\n+\t\t\tdev->intr.bits[vf / max_bits] &=\n+\t\t\t\t~(BIT_ULL(vf % max_bits));\n+\t\t}\n+\t}\n+\tdev->timer_set = 0;\n+}\n+\n+static void\n+roc_vf_pf_mbox_irq(void *param)\n+{\n+\tstruct dev *dev = param;\n+\tbool alarm_set = false;\n+\tuint64_t intr;\n+\tint vfpf;\n+\n+\tfor (vfpf = 0; vfpf < MAX_VFPF_DWORD_BITS; ++vfpf) {\n+\t\tintr = plt_read64(dev->bar2 + RVU_PF_VFPF_MBOX_INTX(vfpf));\n+\t\tif (!intr)\n+\t\t\tcontinue;\n+\n+\t\tplt_base_dbg(\"vfpf: %d intr: 0x%\" PRIx64 \" (pf:%d, vf:%d)\",\n+\t\t\t     vfpf, intr, dev->pf, dev->vf);\n+\n+\t\t/* Save and clear intr bits */\n+\t\tdev->intr.bits[vfpf] |= intr;\n+\t\tplt_write64(intr, dev->bar2 + RVU_PF_VFPF_MBOX_INTX(vfpf));\n+\t\talarm_set = true;\n+\t}\n+\n+\tif (!dev->timer_set && alarm_set) {\n+\t\tdev->timer_set = 1;\n+\t\t/* Start timer to handle messages */\n+\t\tplt_alarm_set(VF_PF_MBOX_TIMER_MS, roc_vf_pf_mbox_handle_msg,\n+\t\t\t      dev);\n+\t}\n+}\n+\n static void\n process_msgs(struct dev *dev, struct mbox *mbox)\n {\n@@ -62,6 +393,112 @@ process_msgs(struct dev *dev, struct mbox *mbox)\n \tplt_wmb();\n }\n \n+/* Copies the message received from AF and sends it to VF */\n+static void\n+pf_vf_mbox_send_up_msg(struct dev *dev, void *rec_msg)\n+{\n+\tuint16_t max_bits = sizeof(dev->active_vfs[0]) * sizeof(uint64_t);\n+\tstruct mbox *vf_mbox = &dev->mbox_vfpf_up;\n+\tstruct msg_req *msg = rec_msg;\n+\tstruct mbox_msghdr *vf_msg;\n+\tuint16_t vf;\n+\tsize_t size;\n+\n+\tsize = PLT_ALIGN(mbox_id2size(msg->hdr.id), MBOX_MSG_ALIGN);\n+\t/* Send UP message to all VF's */\n+\tfor (vf = 0; vf < vf_mbox->ndevs; vf++) {\n+\t\t/* VF active */\n+\t\tif (!(dev->active_vfs[vf / max_bits] & (BIT_ULL(vf))))\n+\t\t\tcontinue;\n+\n+\t\tplt_base_dbg(\"(%s) size: %zx to VF: %d\",\n+\t\t\t     mbox_id2name(msg->hdr.id), size, vf);\n+\n+\t\t/* Reserve PF/VF mbox message */\n+\t\tvf_msg = mbox_alloc_msg(vf_mbox, vf, size);\n+\t\tif (!vf_msg) {\n+\t\t\tplt_err(\"Failed to alloc VF%d UP message\", vf);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tmbox_req_init(msg->hdr.id, vf_msg);\n+\n+\t\t/*\n+\t\t * Copy message from AF<->PF UP mbox\n+\t\t * to PF<->VF UP mbox\n+\t\t */\n+\t\tmbox_memcpy((uint8_t *)vf_msg + sizeof(struct mbox_msghdr),\n+\t\t\t    (uint8_t *)msg + sizeof(struct mbox_msghdr),\n+\t\t\t    size - sizeof(struct mbox_msghdr));\n+\n+\t\tvf_msg->rc = msg->hdr.rc;\n+\t\t/* Set PF to be a sender */\n+\t\tvf_msg->pcifunc = dev->pf_func;\n+\n+\t\t/* Send to VF */\n+\t\tmbox_msg_send(vf_mbox, vf);\n+\t}\n+}\n+\n+static int\n+mbox_up_handler_cgx_link_event(struct dev *dev, struct cgx_link_info_msg *msg,\n+\t\t\t       struct msg_rsp *rsp)\n+{\n+\tstruct cgx_link_user_info *linfo = &msg->link_info;\n+\tvoid *roc_nix = dev->roc_nix;\n+\n+\tplt_base_dbg(\"pf:%d/vf:%d NIC Link %s --> 0x%x (%s) from: pf:%d/vf:%d\",\n+\t\t     dev_get_pf(dev->pf_func), dev_get_vf(dev->pf_func),\n+\t\t     linfo->link_up ? \"UP\" : \"DOWN\", msg->hdr.id,\n+\t\t     mbox_id2name(msg->hdr.id), dev_get_pf(msg->hdr.pcifunc),\n+\t\t     dev_get_vf(msg->hdr.pcifunc));\n+\n+\t/* PF gets link notification from AF */\n+\tif (dev_get_pf(msg->hdr.pcifunc) == 0) {\n+\t\tif (dev->ops && dev->ops->link_status_update)\n+\t\t\tdev->ops->link_status_update(roc_nix, linfo);\n+\n+\t\t/* Forward the same message as received from AF to VF */\n+\t\tpf_vf_mbox_send_up_msg(dev, msg);\n+\t} else {\n+\t\t/* VF gets link up notification */\n+\t\tif (dev->ops && dev->ops->link_status_update)\n+\t\t\tdev->ops->link_status_update(roc_nix, linfo);\n+\t}\n+\n+\trsp->hdr.rc = 0;\n+\treturn 0;\n+}\n+\n+static int\n+mbox_up_handler_cgx_ptp_rx_info(struct dev *dev,\n+\t\t\t\tstruct cgx_ptp_rx_info_msg *msg,\n+\t\t\t\tstruct msg_rsp *rsp)\n+{\n+\tvoid *roc_nix = dev->roc_nix;\n+\n+\tplt_base_dbg(\"pf:%d/vf:%d PTP mode %s --> 0x%x (%s) from: pf:%d/vf:%d\",\n+\t\t     dev_get_pf(dev->pf_func), dev_get_vf(dev->pf_func),\n+\t\t     msg->ptp_en ? \"ENABLED\" : \"DISABLED\", msg->hdr.id,\n+\t\t     mbox_id2name(msg->hdr.id), dev_get_pf(msg->hdr.pcifunc),\n+\t\t     dev_get_vf(msg->hdr.pcifunc));\n+\n+\t/* PF gets PTP notification from AF */\n+\tif (dev_get_pf(msg->hdr.pcifunc) == 0) {\n+\t\tif (dev->ops && dev->ops->ptp_info_update)\n+\t\t\tdev->ops->ptp_info_update(roc_nix, msg->ptp_en);\n+\n+\t\t/* Forward the same message as received from AF to VF */\n+\t\tpf_vf_mbox_send_up_msg(dev, msg);\n+\t} else {\n+\t\t/* VF gets PTP notification */\n+\t\tif (dev->ops && dev->ops->ptp_info_update)\n+\t\t\tdev->ops->ptp_info_update(roc_nix, msg->ptp_en);\n+\t}\n+\n+\trsp->hdr.rc = 0;\n+\treturn 0;\n+}\n+\n static int\n mbox_process_msgs_up(struct dev *dev, struct mbox_msghdr *req)\n {\n@@ -73,6 +510,24 @@ mbox_process_msgs_up(struct dev *dev, struct mbox_msghdr *req)\n \tdefault:\n \t\treply_invalid_msg(&dev->mbox_up, 0, 0, req->id);\n \t\tbreak;\n+#define M(_name, _id, _fn_name, _req_type, _rsp_type)                          \\\n+\tcase _id: {                                                            \\\n+\t\tstruct _rsp_type *rsp;                                         \\\n+\t\tint err;                                                       \\\n+\t\trsp = (struct _rsp_type *)mbox_alloc_msg(                      \\\n+\t\t\t&dev->mbox_up, 0, sizeof(struct _rsp_type));           \\\n+\t\tif (!rsp)                                                      \\\n+\t\t\treturn -ENOMEM;                                        \\\n+\t\trsp->hdr.id = _id;                                             \\\n+\t\trsp->hdr.sig = MBOX_RSP_SIG;                                   \\\n+\t\trsp->hdr.pcifunc = dev->pf_func;                               \\\n+\t\trsp->hdr.rc = 0;                                               \\\n+\t\terr = mbox_up_handler_##_fn_name(dev, (struct _req_type *)req, \\\n+\t\t\t\t\t\t rsp);                         \\\n+\t\treturn err;                                                    \\\n+\t}\n+\t\tMBOX_UP_CGX_MESSAGES\n+#undef M\n \t}\n \n \treturn -ENODEV;\n@@ -111,6 +566,26 @@ process_msgs_up(struct dev *dev, struct mbox *mbox)\n }\n \n static void\n+roc_pf_vf_mbox_irq(void *param)\n+{\n+\tstruct dev *dev = param;\n+\tuint64_t intr;\n+\n+\tintr = plt_read64(dev->bar2 + RVU_VF_INT);\n+\tif (intr == 0)\n+\t\tplt_base_dbg(\"Proceeding to check mbox UP messages if any\");\n+\n+\tplt_write64(intr, dev->bar2 + RVU_VF_INT);\n+\tplt_base_dbg(\"Irq 0x%\" PRIx64 \"(pf:%d,vf:%d)\", intr, dev->pf, dev->vf);\n+\n+\t/* First process all configuration messages */\n+\tprocess_msgs(dev, dev->mbox);\n+\n+\t/* Process Uplink messages */\n+\tprocess_msgs_up(dev, &dev->mbox_up);\n+}\n+\n+static void\n roc_af_pf_mbox_irq(void *param)\n {\n \tstruct dev *dev = param;\n@@ -121,7 +596,7 @@ roc_af_pf_mbox_irq(void *param)\n \t\tplt_base_dbg(\"Proceeding to check mbox UP messages if any\");\n \n \tplt_write64(intr, dev->bar2 + RVU_PF_INT);\n-\tplt_base_dbg(\"Irq 0x%\" PRIx64 \"(pf:%d)\", intr, dev->pf);\n+\tplt_base_dbg(\"Irq 0x%\" PRIx64 \"(pf:%d,vf:%d)\", intr, dev->pf, dev->vf);\n \n \t/* First process all configuration messages */\n \tprocess_msgs(dev, dev->mbox);\n@@ -134,10 +609,33 @@ static int\n mbox_register_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)\n {\n \tstruct plt_intr_handle *intr_handle = &pci_dev->intr_handle;\n-\tint rc;\n+\tint i, rc;\n+\n+\t/* HW clear irq */\n+\tfor (i = 0; i < MAX_VFPF_DWORD_BITS; ++i)\n+\t\tplt_write64(~0ull,\n+\t\t\t    dev->bar2 + RVU_PF_VFPF_MBOX_INT_ENA_W1CX(i));\n \n \tplt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);\n \n+\tdev->timer_set = 0;\n+\n+\t/* MBOX interrupt for VF(0...63) <-> PF */\n+\trc = dev_irq_register(intr_handle, roc_vf_pf_mbox_irq, dev,\n+\t\t\t      RVU_PF_INT_VEC_VFPF_MBOX0);\n+\n+\tif (rc) {\n+\t\tplt_err(\"Fail to register PF(VF0-63) mbox irq\");\n+\t\treturn rc;\n+\t}\n+\t/* MBOX interrupt for VF(64...128) <-> PF */\n+\trc = dev_irq_register(intr_handle, roc_vf_pf_mbox_irq, dev,\n+\t\t\t      RVU_PF_INT_VEC_VFPF_MBOX1);\n+\n+\tif (rc) {\n+\t\tplt_err(\"Fail to register PF(VF64-128) mbox irq\");\n+\t\treturn rc;\n+\t}\n \t/* MBOX interrupt AF <-> PF */\n \trc = dev_irq_register(intr_handle, roc_af_pf_mbox_irq, dev,\n \t\t\t      RVU_PF_INT_VEC_AFPF_MBOX);\n@@ -146,6 +644,11 @@ mbox_register_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)\n \t\treturn rc;\n \t}\n \n+\t/* HW enable intr */\n+\tfor (i = 0; i < MAX_VFPF_DWORD_BITS; ++i)\n+\t\tplt_write64(~0ull,\n+\t\t\t    dev->bar2 + RVU_PF_VFPF_MBOX_INT_ENA_W1SX(i));\n+\n \tplt_write64(~0ull, dev->bar2 + RVU_PF_INT);\n \tplt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1S);\n \n@@ -153,27 +656,263 @@ mbox_register_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)\n }\n \n static int\n+mbox_register_vf_irq(struct plt_pci_device *pci_dev, struct dev *dev)\n+{\n+\tstruct plt_intr_handle *intr_handle = &pci_dev->intr_handle;\n+\tint rc;\n+\n+\t/* Clear irq */\n+\tplt_write64(~0ull, dev->bar2 + RVU_VF_INT_ENA_W1C);\n+\n+\t/* MBOX interrupt PF <-> VF */\n+\trc = dev_irq_register(intr_handle, roc_pf_vf_mbox_irq, dev,\n+\t\t\t      RVU_VF_INT_VEC_MBOX);\n+\tif (rc) {\n+\t\tplt_err(\"Fail to register PF<->VF mbox irq\");\n+\t\treturn rc;\n+\t}\n+\n+\t/* HW enable intr */\n+\tplt_write64(~0ull, dev->bar2 + RVU_VF_INT);\n+\tplt_write64(~0ull, dev->bar2 + RVU_VF_INT_ENA_W1S);\n+\n+\treturn rc;\n+}\n+\n+static int\n mbox_register_irq(struct plt_pci_device *pci_dev, struct dev *dev)\n {\n-\treturn mbox_register_pf_irq(pci_dev, dev);\n+\tif (dev_is_vf(dev))\n+\t\treturn mbox_register_vf_irq(pci_dev, dev);\n+\telse\n+\t\treturn mbox_register_pf_irq(pci_dev, dev);\n }\n \n static void\n mbox_unregister_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)\n {\n \tstruct plt_intr_handle *intr_handle = &pci_dev->intr_handle;\n+\tint i;\n+\n+\t/* HW clear irq */\n+\tfor (i = 0; i < MAX_VFPF_DWORD_BITS; ++i)\n+\t\tplt_write64(~0ull,\n+\t\t\t    dev->bar2 + RVU_PF_VFPF_MBOX_INT_ENA_W1CX(i));\n \n \tplt_write64(~0ull, dev->bar2 + RVU_PF_INT_ENA_W1C);\n \n+\tdev->timer_set = 0;\n+\n+\tplt_alarm_cancel(roc_vf_pf_mbox_handle_msg, dev);\n+\n+\t/* Unregister the interrupt handler for each vectors */\n+\t/* MBOX interrupt for VF(0...63) <-> PF */\n+\tdev_irq_unregister(intr_handle, roc_vf_pf_mbox_irq, dev,\n+\t\t\t   RVU_PF_INT_VEC_VFPF_MBOX0);\n+\n+\t/* MBOX interrupt for VF(64...128) <-> PF */\n+\tdev_irq_unregister(intr_handle, roc_vf_pf_mbox_irq, dev,\n+\t\t\t   RVU_PF_INT_VEC_VFPF_MBOX1);\n+\n \t/* MBOX interrupt AF <-> PF */\n \tdev_irq_unregister(intr_handle, roc_af_pf_mbox_irq, dev,\n \t\t\t   RVU_PF_INT_VEC_AFPF_MBOX);\n }\n \n static void\n+mbox_unregister_vf_irq(struct plt_pci_device *pci_dev, struct dev *dev)\n+{\n+\tstruct plt_intr_handle *intr_handle = &pci_dev->intr_handle;\n+\n+\t/* Clear irq */\n+\tplt_write64(~0ull, dev->bar2 + RVU_VF_INT_ENA_W1C);\n+\n+\t/* Unregister the interrupt handler */\n+\tdev_irq_unregister(intr_handle, roc_pf_vf_mbox_irq, dev,\n+\t\t\t   RVU_VF_INT_VEC_MBOX);\n+}\n+\n+static void\n mbox_unregister_irq(struct plt_pci_device *pci_dev, struct dev *dev)\n {\n-\tmbox_unregister_pf_irq(pci_dev, dev);\n+\tif (dev_is_vf(dev))\n+\t\tmbox_unregister_vf_irq(pci_dev, dev);\n+\telse\n+\t\tmbox_unregister_pf_irq(pci_dev, dev);\n+}\n+\n+static int\n+vf_flr_send_msg(struct dev *dev, uint16_t vf)\n+{\n+\tstruct mbox *mbox = dev->mbox;\n+\tstruct msg_req *req;\n+\tint rc;\n+\n+\treq = mbox_alloc_msg_vf_flr(mbox);\n+\tif (req == NULL)\n+\t\treturn -ENOSPC;\n+\t/* Overwrite pcifunc to indicate VF */\n+\treq->hdr.pcifunc = dev_pf_func(dev->pf, vf);\n+\n+\t/* Sync message in interrupt context */\n+\trc = pf_af_sync_msg(dev, NULL);\n+\tif (rc)\n+\t\tplt_err(\"Failed to send VF FLR mbox msg, rc=%d\", rc);\n+\n+\treturn rc;\n+}\n+\n+static void\n+roc_pf_vf_flr_irq(void *param)\n+{\n+\tstruct dev *dev = (struct dev *)param;\n+\tuint16_t max_vf = 64, vf;\n+\tuintptr_t bar2;\n+\tuint64_t intr;\n+\tint i;\n+\n+\tmax_vf = (dev->maxvf > 0) ? dev->maxvf : 64;\n+\tbar2 = dev->bar2;\n+\n+\tplt_base_dbg(\"FLR VF interrupt: max_vf: %d\", max_vf);\n+\n+\tfor (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {\n+\t\tintr = plt_read64(bar2 + RVU_PF_VFFLR_INTX(i));\n+\t\tif (!intr)\n+\t\t\tcontinue;\n+\n+\t\tfor (vf = 0; vf < max_vf; vf++) {\n+\t\t\tif (!(intr & (1ULL << vf)))\n+\t\t\t\tcontinue;\n+\n+\t\t\tplt_base_dbg(\"FLR: i :%d intr: 0x%\" PRIx64 \", vf-%d\", i,\n+\t\t\t\t     intr, (64 * i + vf));\n+\t\t\t/* Clear interrupt */\n+\t\t\tplt_write64(BIT_ULL(vf), bar2 + RVU_PF_VFFLR_INTX(i));\n+\t\t\t/* Disable the interrupt */\n+\t\t\tplt_write64(BIT_ULL(vf),\n+\t\t\t\t    bar2 + RVU_PF_VFFLR_INT_ENA_W1CX(i));\n+\t\t\t/* Inform AF about VF reset */\n+\t\t\tvf_flr_send_msg(dev, vf);\n+\n+\t\t\t/* Signal FLR finish */\n+\t\t\tplt_write64(BIT_ULL(vf), bar2 + RVU_PF_VFTRPENDX(i));\n+\t\t\t/* Enable interrupt */\n+\t\t\tplt_write64(~0ull, bar2 + RVU_PF_VFFLR_INT_ENA_W1SX(i));\n+\t\t}\n+\t}\n+}\n+\n+static int\n+vf_flr_unregister_irqs(struct plt_pci_device *pci_dev, struct dev *dev)\n+{\n+\tstruct plt_intr_handle *intr_handle = &pci_dev->intr_handle;\n+\tint i;\n+\n+\tplt_base_dbg(\"Unregister VF FLR interrupts for %s\", pci_dev->name);\n+\n+\t/* HW clear irq */\n+\tfor (i = 0; i < MAX_VFPF_DWORD_BITS; i++)\n+\t\tplt_write64(~0ull, dev->bar2 + RVU_PF_VFFLR_INT_ENA_W1CX(i));\n+\n+\tdev_irq_unregister(intr_handle, roc_pf_vf_flr_irq, dev,\n+\t\t\t   RVU_PF_INT_VEC_VFFLR0);\n+\n+\tdev_irq_unregister(intr_handle, roc_pf_vf_flr_irq, dev,\n+\t\t\t   RVU_PF_INT_VEC_VFFLR1);\n+\n+\treturn 0;\n+}\n+\n+static int\n+vf_flr_register_irqs(struct plt_pci_device *pci_dev, struct dev *dev)\n+{\n+\tstruct plt_intr_handle *handle = &pci_dev->intr_handle;\n+\tint i, rc;\n+\n+\tplt_base_dbg(\"Register VF FLR interrupts for %s\", pci_dev->name);\n+\n+\trc = dev_irq_register(handle, roc_pf_vf_flr_irq, dev,\n+\t\t\t      RVU_PF_INT_VEC_VFFLR0);\n+\tif (rc)\n+\t\tplt_err(\"Failed to init RVU_PF_INT_VEC_VFFLR0 rc=%d\", rc);\n+\n+\trc = dev_irq_register(handle, roc_pf_vf_flr_irq, dev,\n+\t\t\t      RVU_PF_INT_VEC_VFFLR1);\n+\tif (rc)\n+\t\tplt_err(\"Failed to init RVU_PF_INT_VEC_VFFLR1 rc=%d\", rc);\n+\n+\t/* Enable HW interrupt */\n+\tfor (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {\n+\t\tplt_write64(~0ull, dev->bar2 + RVU_PF_VFFLR_INTX(i));\n+\t\tplt_write64(~0ull, dev->bar2 + RVU_PF_VFTRPENDX(i));\n+\t\tplt_write64(~0ull, dev->bar2 + RVU_PF_VFFLR_INT_ENA_W1SX(i));\n+\t}\n+\treturn 0;\n+}\n+\n+int\n+dev_active_vfs(struct dev *dev)\n+{\n+\tint i, count = 0;\n+\n+\tfor (i = 0; i < MAX_VFPF_DWORD_BITS; i++)\n+\t\tcount += __builtin_popcount(dev->active_vfs[i]);\n+\n+\treturn count;\n+}\n+\n+static void\n+dev_vf_hwcap_update(struct plt_pci_device *pci_dev, struct dev *dev)\n+{\n+\tswitch (pci_dev->id.device_id) {\n+\tcase PCI_DEVID_CNXK_RVU_PF:\n+\t\tbreak;\n+\tcase PCI_DEVID_CNXK_RVU_SSO_TIM_VF:\n+\tcase PCI_DEVID_CNXK_RVU_NPA_VF:\n+\tcase PCI_DEVID_CNXK_RVU_AF_VF:\n+\tcase PCI_DEVID_CNXK_RVU_VF:\n+\tcase PCI_DEVID_CNXK_RVU_SDP_VF:\n+\t\tdev->hwcap |= DEV_HWCAP_F_VF;\n+\t\tbreak;\n+\t}\n+}\n+\n+static uintptr_t\n+dev_vf_mbase_get(struct plt_pci_device *pci_dev, struct dev *dev)\n+{\n+\tvoid *vf_mbase = NULL;\n+\tuintptr_t pa;\n+\n+\tif (dev_is_vf(dev))\n+\t\treturn 0;\n+\n+\t/* For CN10K onwards, it is just after PF MBOX */\n+\tif (!roc_model_is_cn9k())\n+\t\treturn dev->bar4 + MBOX_SIZE;\n+\n+\tpa = plt_read64(dev->bar2 + RVU_PF_VF_BAR4_ADDR);\n+\tif (!pa) {\n+\t\tplt_err(\"Invalid VF mbox base pa\");\n+\t\treturn pa;\n+\t}\n+\n+\tvf_mbase = mbox_mem_map(pa, MBOX_SIZE * pci_dev->max_vfs);\n+\tif (vf_mbase == MAP_FAILED) {\n+\t\tplt_err(\"Failed to mmap vf mbase at pa 0x%lx, rc=%d\", pa,\n+\t\t\terrno);\n+\t\treturn 0;\n+\t}\n+\treturn (uintptr_t)vf_mbase;\n+}\n+\n+static void\n+dev_vf_mbase_put(struct plt_pci_device *pci_dev, uintptr_t vf_mbase)\n+{\n+\tif (!vf_mbase || !pci_dev->max_vfs || !roc_model_is_cn9k())\n+\t\treturn;\n+\n+\tmbox_mem_unmap((void *)vf_mbase, MBOX_SIZE * pci_dev->max_vfs);\n }\n \n static uint16_t\n@@ -213,7 +952,6 @@ dev_setup_shared_lmt_region(struct mbox *mbox)\n static int\n dev_lmt_setup(struct plt_pci_device *pci_dev, struct dev *dev)\n {\n-\tuint64_t bar4_mbox_sz = MBOX_SIZE;\n \tstruct idev_cfg *idev;\n \tint rc;\n \n@@ -237,19 +975,34 @@ dev_lmt_setup(struct plt_pci_device *pci_dev, struct dev *dev)\n \t\t\tdev->pf_func, rc);\n \t}\n \n-\t/* PF BAR4 should always be sufficient enough to\n-\t * hold PF-AF MBOX + PF-VF MBOX + LMT lines.\n-\t */\n-\tif (pci_dev->mem_resource[4].len <\n-\t    (bar4_mbox_sz + (RVU_LMT_LINE_MAX * RVU_LMT_SZ))) {\n-\t\tplt_err(\"Not enough bar4 space for lmt lines and mbox\");\n-\t\treturn -EFAULT;\n+\tif (dev_is_vf(dev)) {\n+\t\t/* VF BAR4 should always be sufficient enough to\n+\t\t * hold LMT lines.\n+\t\t */\n+\t\tif (pci_dev->mem_resource[4].len <\n+\t\t    (RVU_LMT_LINE_MAX * RVU_LMT_SZ)) {\n+\t\t\tplt_err(\"Not enough bar4 space for lmt lines\");\n+\t\t\treturn -EFAULT;\n+\t\t}\n+\n+\t\tdev->lmt_base = dev->bar4;\n+\t} else {\n+\t\tuint64_t bar4_mbox_sz = MBOX_SIZE;\n+\n+\t\t/* PF BAR4 should always be sufficient enough to\n+\t\t * hold PF-AF MBOX + PF-VF MBOX + LMT lines.\n+\t\t */\n+\t\tif (pci_dev->mem_resource[4].len <\n+\t\t    (bar4_mbox_sz + (RVU_LMT_LINE_MAX * RVU_LMT_SZ))) {\n+\t\t\tplt_err(\"Not enough bar4 space for lmt lines and mbox\");\n+\t\t\treturn -EFAULT;\n+\t\t}\n+\n+\t\t/* LMT base is just after total VF MBOX area */\n+\t\tbar4_mbox_sz += (MBOX_SIZE * dev_pf_total_vfs(pci_dev));\n+\t\tdev->lmt_base = dev->bar4 + bar4_mbox_sz;\n \t}\n \n-\t/* LMT base is just after total VF MBOX area */\n-\tbar4_mbox_sz += (MBOX_SIZE * dev_pf_total_vfs(pci_dev));\n-\tdev->lmt_base = dev->bar4 + bar4_mbox_sz;\n-\n \t/* Base LMT address should be chosen from only those pci funcs which\n \t * participate in LMT shared mode.\n \t */\n@@ -270,6 +1023,7 @@ dev_init(struct dev *dev, struct plt_pci_device *pci_dev)\n {\n \tint direction, up_direction, rc;\n \tuintptr_t bar2, bar4, mbox;\n+\tuintptr_t vf_mbase = 0;\n \tuint64_t intr_offset;\n \n \tbar2 = (uintptr_t)pci_dev->mem_resource[2].addr;\n@@ -293,13 +1047,23 @@ dev_init(struct dev *dev, struct plt_pci_device *pci_dev)\n \t\tgoto error;\n \t}\n \n+\tdev->maxvf = pci_dev->max_vfs;\n \tdev->bar2 = bar2;\n \tdev->bar4 = bar4;\n+\tdev_vf_hwcap_update(pci_dev, dev);\n \n-\tmbox = bar4;\n-\tdirection = MBOX_DIR_PFAF;\n-\tup_direction = MBOX_DIR_PFAF_UP;\n-\tintr_offset = RVU_PF_INT;\n+\tif (dev_is_vf(dev)) {\n+\t\tmbox = (roc_model_is_cn9k() ?\n+\t\t\tbar4 : (bar2 + RVU_VF_MBOX_REGION));\n+\t\tdirection = MBOX_DIR_VFPF;\n+\t\tup_direction = MBOX_DIR_VFPF_UP;\n+\t\tintr_offset = RVU_VF_INT;\n+\t} else {\n+\t\tmbox = bar4;\n+\t\tdirection = MBOX_DIR_PFAF;\n+\t\tup_direction = MBOX_DIR_PFAF_UP;\n+\t\tintr_offset = RVU_PF_INT;\n+\t}\n \n \t/* Initialize the local mbox */\n \trc = mbox_init(&dev->mbox_local, mbox, bar2, direction, 1, intr_offset);\n@@ -322,7 +1086,43 @@ dev_init(struct dev *dev, struct plt_pci_device *pci_dev)\n \t\tgoto mbox_unregister;\n \n \tdev->pf = dev_get_pf(dev->pf_func);\n+\tdev->vf = dev_get_vf(dev->pf_func);\n+\tmemset(&dev->active_vfs, 0, sizeof(dev->active_vfs));\n \n+\t/* Allocate memory for device ops */\n+\tdev->ops = plt_zmalloc(sizeof(struct dev_ops), 0);\n+\tif (dev->ops == NULL) {\n+\t\trc = -ENOMEM;\n+\t\tgoto mbox_unregister;\n+\t}\n+\n+\t/* Found VF devices in a PF device */\n+\tif (pci_dev->max_vfs > 0) {\n+\t\t/* Remap mbox area for all vf's */\n+\t\tvf_mbase = dev_vf_mbase_get(pci_dev, dev);\n+\t\tif (!vf_mbase) {\n+\t\t\trc = -ENODEV;\n+\t\t\tgoto mbox_unregister;\n+\t\t}\n+\t\t/* Init mbox object */\n+\t\trc = mbox_init(&dev->mbox_vfpf, vf_mbase, bar2, MBOX_DIR_PFVF,\n+\t\t\t       pci_dev->max_vfs, intr_offset);\n+\t\tif (rc)\n+\t\t\tgoto iounmap;\n+\n+\t\t/* PF -> VF UP messages */\n+\t\trc = mbox_init(&dev->mbox_vfpf_up, vf_mbase, bar2,\n+\t\t\t       MBOX_DIR_PFVF_UP, pci_dev->max_vfs, intr_offset);\n+\t\tif (rc)\n+\t\t\tgoto iounmap;\n+\t}\n+\n+\t/* Register VF-FLR irq handlers */\n+\tif (!dev_is_vf(dev)) {\n+\t\trc = vf_flr_register_irqs(pci_dev, dev);\n+\t\tif (rc)\n+\t\t\tgoto iounmap;\n+\t}\n \tdev->mbox_active = 1;\n \n \t/* Setup LMT line base */\n@@ -332,8 +1132,11 @@ dev_init(struct dev *dev, struct plt_pci_device *pci_dev)\n \n \treturn rc;\n iounmap:\n+\tdev_vf_mbase_put(pci_dev, vf_mbase);\n mbox_unregister:\n \tmbox_unregister_irq(pci_dev, dev);\n+\tif (dev->ops)\n+\t\tplt_free(dev->ops);\n mbox_fini:\n \tmbox_fini(dev->mbox);\n \tmbox_fini(&dev->mbox_up);\n@@ -349,6 +1152,20 @@ dev_fini(struct dev *dev, struct plt_pci_device *pci_dev)\n \n \tmbox_unregister_irq(pci_dev, dev);\n \n+\tif (!dev_is_vf(dev))\n+\t\tvf_flr_unregister_irqs(pci_dev, dev);\n+\t/* Release PF - VF */\n+\tmbox = &dev->mbox_vfpf;\n+\tif (mbox->hwbase && mbox->dev)\n+\t\tdev_vf_mbase_put(pci_dev, mbox->hwbase);\n+\n+\tif (dev->ops)\n+\t\tplt_free(dev->ops);\n+\n+\tmbox_fini(mbox);\n+\tmbox = &dev->mbox_vfpf_up;\n+\tmbox_fini(mbox);\n+\n \t/* Release PF - AF */\n \tmbox = dev->mbox;\n \tmbox_fini(mbox);\ndiff --git a/drivers/common/cnxk/roc_dev_priv.h b/drivers/common/cnxk/roc_dev_priv.h\nindex c0308e7..d20b089 100644\n--- a/drivers/common/cnxk/roc_dev_priv.h\n+++ b/drivers/common/cnxk/roc_dev_priv.h\n@@ -5,12 +5,38 @@\n #ifndef _ROC_DEV_PRIV_H\n #define _ROC_DEV_PRIV_H\n \n+#define DEV_HWCAP_F_VF BIT_ULL(0) /* VF device */\n+\n #define RVU_PFVF_PF_SHIFT   10\n #define RVU_PFVF_PF_MASK    0x3F\n #define RVU_PFVF_FUNC_SHIFT 0\n #define RVU_PFVF_FUNC_MASK  0x3FF\n+#define RVU_MAX_VF\t    64 /* RVU_PF_VFPF_MBOX_INT(0..1) */\n #define RVU_MAX_INT_RETRY   3\n \n+/* PF/VF message handling timer */\n+#define VF_PF_MBOX_TIMER_MS (20 * 1000)\n+\n+typedef struct {\n+/* 128 devices translate to two 64 bits dwords */\n+#define MAX_VFPF_DWORD_BITS 2\n+\tuint64_t bits[MAX_VFPF_DWORD_BITS];\n+} dev_intr_t;\n+\n+/* Link status update callback */\n+typedef void (*link_info_t)(void *roc_nix,\n+\t\t\t    struct cgx_link_user_info *link);\n+\n+/* PTP info callback */\n+typedef int (*ptp_info_t)(void *roc_nix, bool enable);\n+\n+struct dev_ops {\n+\tlink_info_t link_status_update;\n+\tptp_info_t ptp_info_update;\n+};\n+\n+#define dev_is_vf(dev) ((dev)->hwcap & DEV_HWCAP_F_VF)\n+\n static inline int\n dev_get_vf(uint16_t pf_func)\n {\n@@ -29,18 +55,33 @@ dev_pf_func(int pf, int vf)\n \treturn (pf << RVU_PFVF_PF_SHIFT) | ((vf << RVU_PFVF_FUNC_SHIFT) + 1);\n }\n \n+static inline int\n+dev_is_afvf(uint16_t pf_func)\n+{\n+\treturn !(pf_func & ~RVU_PFVF_FUNC_MASK);\n+}\n+\n struct dev {\n \tuint16_t pf;\n+\tint16_t vf;\n \tuint16_t pf_func;\n \tuint8_t mbox_active;\n \tbool drv_inited;\n+\tuint64_t active_vfs[MAX_VFPF_DWORD_BITS];\n \tuintptr_t bar2;\n \tuintptr_t bar4;\n \tuintptr_t lmt_base;\n \tstruct mbox mbox_local;\n \tstruct mbox mbox_up;\n+\tstruct mbox mbox_vfpf;\n+\tstruct mbox mbox_vfpf_up;\n+\tdev_intr_t intr;\n+\tint timer_set; /* ~0 : no alarm handling */\n \tuint64_t hwcap;\n \tstruct mbox *mbox;\n+\tuint16_t maxvf;\n+\tstruct dev_ops *ops;\n+\tvoid *roc_nix;\n \tbool disable_shared_lmt; /* false(default): shared lmt mode enabled */\n } __plt_cache_aligned;\n \n@@ -49,6 +90,7 @@ extern uint16_t dev_sclk_freq;\n \n int dev_init(struct dev *dev, struct plt_pci_device *pci_dev);\n int dev_fini(struct dev *dev, struct plt_pci_device *pci_dev);\n+int dev_active_vfs(struct dev *dev);\n \n int dev_irq_register(struct plt_intr_handle *intr_handle,\n \t\t     plt_intr_callback_fn cb, void *data, unsigned int vec);\n",
    "prefixes": [
        "v3",
        "08/52"
    ]
}