<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Verdana;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
        {font-family:Aptos;
        panose-1:2 11 0 4 2 2 2 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style>
</head>
<body lang="en-UA" link="#0563C1" vlink="#954F72" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US">Hi Ferruh</span><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US">,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US"><br>
Please find our explanation for your comment according to device initialization</span><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US"> by function
</span><span style="font-size:11.0pt;font-family:"Verdana",sans-serif;color:#212121">nthw_pci_dev_init</span><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;color:#212121">.</span><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US">Our NIC handles multiple ports within the same PCI Bus Device Function (BDF) - hence, we need to create several ETH devices during the probe init.<br>
Allocation of multiple eth devices is handled inside the nthw_pci_dev_init() function.<br>
It appears to be similar to what the Octeontx driver does.</span><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US">We believe the current implementation fits better for our PMD, so we would like to keep it as is, unless it is a blocking requirement for upstreaming.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US">Please let us know.</span><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US">BR,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Verdana",sans-serif;mso-fareast-language:EN-US">Serhii</span><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<div id="mail-editor-reference-message-container">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;font-family:"Aptos",sans-serif;color:black">From:
</span></b><span style="font-size:12.0pt;font-family:"Aptos",sans-serif;color:black">Ferruh Yigit <ferruh.yigit@amd.com><br>
<b>Date: </b>Friday, 5 July 2024 at 01:44<br>
<b>To: </b>Serhii Iliushyk <sil-plv@napatech.com>, dev@dpdk.org <dev@dpdk.org><br>
<b>Cc: </b>Mykola Kostenok <mko-plv@napatech.com>, Christian Koue Muf <ckm@napatech.com>, andrew.rybchenko@oktetlabs.ru <andrew.rybchenko@oktetlabs.ru><br>
<b>Subject: </b>Re: [PATCH v5 03/23] net/ntnic: add minimal initialization for PCI device<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt">On 6/27/2024 8:38 AM, Serhii Iliushyk wrote:<br>
> add implementation for probe/init and remove/deinit of the PCI device<br>
> <br>
> Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com><br>
> ---<br>
>  drivers/net/ntnic/ntnic_ethdev.c | 104 ++++++++++++++++++++++++++++++-<br>
>  1 file changed, 103 insertions(+), 1 deletion(-)<br>
> <br>
> diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c<br>
> index 3079bd98e4..e9a584877f 100644<br>
> --- a/drivers/net/ntnic/ntnic_ethdev.c<br>
> +++ b/drivers/net/ntnic/ntnic_ethdev.c<br>
> @@ -17,14 +17,63 @@<br>
>  /* Global static variables: */<br>
>  <br>
>  static int<br>
> -nthw_pci_dev_init(struct rte_pci_device *pci_dev __rte_unused)<br>
> +nthw_pci_dev_init(struct rte_pci_device *pci_dev)<br>
>  {<br>
> +     uint32_t n_port_mask = -1;      /* All ports enabled by default */<br>
> +     int n_phy_ports;<br>
> +     NT_LOG_DBGX(DEBUG, NTNIC, "Dev %s PF #%i Init : %02x:%02x:%i\n", pci_dev->name,<br>
> +             pci_dev->addr.function, pci_dev->addr.bus, pci_dev->addr.devid,<br>
> +             pci_dev->addr.function);<br>
> +<br>
> +     n_phy_ports = 0;<br>
> +<br>
> +     for (int n_intf_no = 0; n_intf_no < n_phy_ports; n_intf_no++) {<br>
> +             struct rte_eth_dev *eth_dev = NULL;<br>
> +             char name[32];<br>
> +<br>
> +             if ((1 << n_intf_no) & ~n_port_mask)<br>
> +                     continue;<br>
> +<br>
> +             snprintf(name, sizeof(name), "ntnic%d", n_intf_no);<br>
> +<br>
> +             eth_dev = rte_eth_dev_allocate(name);   /* TODO: name */<br>
><br>
<br>
Is this TODO still valid?<br>
<br>
> +<br>
> +             if (!eth_dev) {<br>
> +                     NT_LOG_DBGX(ERR, NTNIC, "%s: %s: error=%d\n",<br>
> +                             (pci_dev->name[0] ? pci_dev->name : "NA"), name, -1);<br>
> +                     return -1;<br>
> +             }<br>
> +<br>
> +             NT_LOG_DBGX(DEBUG, NTNIC, "eth_dev %p, port_id %u, if_index %u\n",<br>
> +                                     eth_dev, eth_dev->data->port_id, n_intf_no);<br>
> +<br>
> +<br>
> +             struct rte_eth_link pmd_link;<br>
> +             pmd_link.link_speed = RTE_ETH_SPEED_NUM_NONE;<br>
> +             pmd_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;<br>
> +             pmd_link.link_status = RTE_ETH_LINK_DOWN;<br>
> +             pmd_link.link_autoneg = RTE_ETH_LINK_AUTONEG;<br>
> +<br>
> +             eth_dev->device = &pci_dev->device;<br>
> +             eth_dev->data->dev_link = pmd_link;<br>
> +             eth_dev->data->numa_node = pci_dev->device.numa_node;<br>
><br>
<br>
rte_eth_copy_pci_info() should be setting numa_node, no need to<br>
duplicate here.<br>
<br>
Please consider using 'rte_eth_dev_create()' to help these kind of<br>
boilerplate initialization. I did same comment below.<br>
<br>
> +             eth_dev->dev_ops = NULL;<br>
> +             eth_dev->state = RTE_ETH_DEV_ATTACHED;<br>
><br>
<br>
Shouldn't need to set state directly, please call<br>
'rte_eth_dev_probing_finish()' as a last thing in probe().<br>
This call will set the state, also will do some other required work.<br>
<br>
> +<br>
> +             rte_eth_copy_pci_info(eth_dev, pci_dev);<br>
> +             /* performs rte_eth_copy_pci_info() */<br>
> +             eth_dev_pci_specific_init(eth_dev, pci_dev);<br>
><br>
<br>
As comment says, 'eth_dev_pci_specific_init()' calls the<br>
'rte_eth_copy_pci_info()', so why calling it twice, can clean the init<br>
and remove the comment.<br>
<br>
> +<br>
> +             /* increase initialized ethernet devices - PF */<br>
><br>
<br>
Is this comment valid here?<br>
<br>
> +     }<br>
> +<br>
>        return 0;<br>
>  }<br>
>  <br>
>  static int<br>
>  nthw_pci_dev_deinit(struct rte_eth_dev *eth_dev __rte_unused)<br>
>  {<br>
> +     NT_LOG_DBGX(DEBUG, NTNIC, "PCI device deinitialization\n");<br>
>        return 0;<br>
>  }<br>
>  <br>
> @@ -33,13 +82,65 @@ nthw_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,<br>
>        struct rte_pci_device *pci_dev)<br>
>  {<br>
>        int res;<br>
> +<br>
> +     NT_LOG_DBGX(DEBUG, NTNIC, "pcidev: name: '%s'\n", pci_dev->name);<br>
> +     NT_LOG_DBGX(DEBUG, NTNIC, "devargs: name: '%s'\n", pci_dev->https://linkprotect.cudasvc.com/url?a=https%3a%2f%2fdevice.name&c=E,1,V5OBhPhfiNSro_oj2bitVYkKYAABsPx-MKLgmN0q8g6JbMwgnOO1gKkhj3c3IxCQvEgNbC8ofBuQUVC8VRFgpnK79cZnIRMu2iT6BvGGlWlO-BxzlAK2eTwkKk9z&typo=1);<br>
> +<br>
> +     if (pci_dev->device.devargs) {<br>
> +             NT_LOG_DBGX(DEBUG, NTNIC, "devargs: args: '%s'\n",<br>
> +                     (pci_dev->device.devargs->args ? pci_dev->device.devargs->args : "NULL"));<br>
> +             NT_LOG_DBGX(DEBUG, NTNIC, "devargs: data: '%s'\n",<br>
> +                     (pci_dev->device.devargs->data ? pci_dev->device.devargs->data : "NULL"));<br>
> +     }<br>
> +<br>
> +     const int n_rte_has_pci = rte_eal_has_pci();<br>
> +     NT_LOG(DBG, NTNIC, "has_pci=%d\n", n_rte_has_pci);<br>
> +<br>
> +     if (n_rte_has_pci == 0) {<br>
> +             NT_LOG(ERR, NTNIC, "has_pci=%d: this PMD needs hugepages\n", n_rte_has_pci);<br>
><br>
<br>
It is checking PCI bus, but log is about hugepages.<br>
<br>
> +             return -1;<br>
> +     }<br>
><br>
<br>
What is the intention here for the 'n_rte_has_pci' check?<br>
If pci bus is disabled, this probe call should not be called at all, in<br>
that manner this check is useless.<br>
<br>
> +<br>
> +     const int n_rte_vfio_no_io_mmu_enabled = rte_vfio_noiommu_is_enabled();<br>
> +     NT_LOG(DBG, NTNIC, "vfio_no_iommu_enabled=%d\n", n_rte_vfio_no_io_mmu_enabled);<br>
> +<br>
> +     if (n_rte_vfio_no_io_mmu_enabled) {<br>
> +             NT_LOG(ERR, NTNIC, "vfio_no_iommu_enabled=%d: this PMD needs VFIO IOMMU\n",<br>
> +                     n_rte_vfio_no_io_mmu_enabled);<br>
> +             return -1;<br>
> +     }<br>
> +<br>
> +     const enum rte_iova_mode n_rte_io_va_mode = rte_eal_iova_mode();<br>
> +     NT_LOG(DBG, NTNIC, "iova mode=%d\n", n_rte_io_va_mode);<br>
> +<br>
> +     if (n_rte_io_va_mode != RTE_IOVA_PA) {<br>
> +             NT_LOG(WRN, NTNIC, "iova mode (%d) should be PA for performance reasons\n",<br>
> +                     n_rte_io_va_mode);<br>
> +     }<br>
><br>
<br>
Is this comment valid?<br>
Won't iommu be used for address translation both IOVA_VA and IOVA_PA<br>
mode? How much performance improvement we are talking about?<br>
<br>
> +<br>
> +     NT_LOG(DBG, NTNIC,<br>
> +             "busid=" PCI_PRI_FMT<br>
> +             " pciid=%04x:%04x_%04x:%04x locstr=%s @ numanode=%d: drv=%s drvalias=%s\n",<br>
> +             pci_dev->addr.domain, pci_dev->addr.bus, pci_dev->addr.devid,<br>
> +             pci_dev->addr.function, pci_dev->id.vendor_id, pci_dev->id.device_id,<br>
> +             pci_dev->id.subsystem_vendor_id, pci_dev->id.subsystem_device_id,<br>
> +             pci_dev->name[0] ? pci_dev->name : "NA",        /* locstr */<br>
> +             pci_dev->device.numa_node,<br>
> +             pci_dev->driver->https://linkprotect.cudasvc.com/url?a=https%3a%2f%2fdriver.name&c=E,1,5_F-hniqJt0w3GPG-nclekQA5nc17FmonNihbX6JRyTd2j6RA7sGlIJ9gBTq_T3p01-6DsO244rVP-3PFWsjaqFJ44V77omLRmCrWio_VmtBudxV30mhcou9&typo=1 ? pci_dev->driver->https://linkprotect.cudasvc.com/url?a=https%3a%2f%2fdriver.name&c=E,1,frkLGUymGHY5ydpNKtk3f74kNLD7KupomSqM7BLD7aOyg83VIXzNCZfCJI9PDNuIjnexaqLnATwKsfczOq1DvmsNBhMbEgTT0QrJ7RKHxIw,&typo=1
 : "NA",<br>
> +             pci_dev->driver->driver.alias ? pci_dev->driver->driver.alias : "NA");<br>
> +<br>
> +<br>
>        res = nthw_pci_dev_init(pci_dev);<br>
><br>
<br>
Instead of calling 'nthw_pci_dev_init()' directly, you can use<br>
'rte_eth_dev_create()' and pass 'nthw_pci_dev_init()' as paramter, this<br>
helps on some set of boilerplate code.<br>
<br>
> +<br>
> +     NT_LOG_DBGX(DEBUG, NTNIC, "leave: res=%d\n", res);<br>
>        return res;<br>
><br>
<br>
Doesn't really matter but mostly 'ret' is used as short version of<br>
"return value", what 'res' is?<br>
<br>
<br>
>  }<br>
>  <br>
>  static int<br>
>  nthw_pci_remove(struct rte_pci_device *pci_dev)<br>
>  {<br>
> +     NT_LOG_DBGX(DEBUG, NTNIC);<br>
> +<br>
>        return rte_eth_dev_pci_generic_remove(pci_dev, nthw_pci_dev_deinit);<br>
>  }<br>
>  <br>
> @@ -48,6 +149,7 @@ static struct rte_pci_driver rte_nthw_pmd = {<br>
>                .name = "net_ntnic",<br>
>        },<br>
>  <br>
> +     .drv_flags = RTE_PCI_DRV_NEED_MAPPING,<br>
>        .probe = nthw_pci_probe,<br>
>        .remove = nthw_pci_remove,<br>
>  };<o:p></o:p></span></p>
</div>
</div>
</div>
</div>
</body>
</html>