DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [RFC] ethdev: complete closing to free all resources
@ 2018-09-07 23:39 Thomas Monjalon
  2018-09-10  8:03 ` Andrew Rybchenko
                   ` (6 more replies)
  0 siblings, 7 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-09-07 23:39 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev

After closing a port, it cannot be restarted.
So there is no reason to not free all associated resources.

The last step was done with rte_eth_dev_detach() which is deprecated.
Instead of removing the associated rte_device, the driver should check
if no more port (ethdev, cryptodev, etc) is still open for the device.
Then the device resources can be freed by the driver inside the
dev_close() driver callback operation.

The last ethdev freeing (dev_private and final release), which were done
by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
This patch contains only the change in the close function as RFC.

This idea was presented at Dublin during the "hotplug talk".
---
 lib/librte_ethdev/rte_ethdev.c | 5 +++++
 lib/librte_ethdev/rte_ethdev.h | 5 +++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 4c3202505..071fcbd23 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -1358,6 +1358,7 @@ void
 rte_eth_dev_close(uint16_t port_id)
 {
 	struct rte_eth_dev *dev;
+	struct rte_bus *bus;
 
 	RTE_ETH_VALID_PORTID_OR_RET(port_id);
 	dev = &rte_eth_devices[port_id];
@@ -1372,6 +1373,10 @@ rte_eth_dev_close(uint16_t port_id)
 	dev->data->nb_tx_queues = 0;
 	rte_free(dev->data->tx_queues);
 	dev->data->tx_queues = NULL;
+
+	rte_free(dev->data->dev_private);
+
+	rte_eth_dev_release_port(dev);
 }
 
 int
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index 7070e9ab4..37a757a7a 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1797,8 +1797,9 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
 
 /**
  * Close a stopped Ethernet device. The device cannot be restarted!
- * The function frees all resources except for needed by the
- * closed state. To free these resources, call rte_eth_dev_detach().
+ * The function frees all port resources.
+ * If there is no more port associated with the underlying device,
+ * the driver should free the device resources.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
-- 
2.18.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [RFC] ethdev: complete closing to free all resources
  2018-09-07 23:39 [dpdk-dev] [RFC] ethdev: complete closing to free all resources Thomas Monjalon
@ 2018-09-10  8:03 ` Andrew Rybchenko
  2018-09-10  8:42   ` Thomas Monjalon
  2018-09-28 12:46 ` Ferruh Yigit
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-09-10  8:03 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit; +Cc: dev

On 09/08/2018 02:39 AM, Thomas Monjalon wrote:
> After closing a port, it cannot be restarted.
> So there is no reason to not free all associated resources.
>
> The last step was done with rte_eth_dev_detach() which is deprecated.
> Instead of removing the associated rte_device, the driver should check
> if no more port (ethdev, cryptodev, etc) is still open for the device.
> Then the device resources can be freed by the driver inside the
> dev_close() driver callback operation.
>
> The last ethdev freeing (dev_private and final release), which were done
> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().

For me, it sounds more logical to kill dev_close and keep detach.
IMHO, dev_close is artificial and hardly useful. detach is a local pair 
to attach.

Anyway it requires update of all drivers as I understand.

> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
> This patch contains only the change in the close function as RFC.
>
> This idea was presented at Dublin during the "hotplug talk".
> ---
>   lib/librte_ethdev/rte_ethdev.c | 5 +++++
>   lib/librte_ethdev/rte_ethdev.h | 5 +++--
>   2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index 4c3202505..071fcbd23 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -1358,6 +1358,7 @@ void
>   rte_eth_dev_close(uint16_t port_id)
>   {
>   	struct rte_eth_dev *dev;
> +	struct rte_bus *bus;
>   
>   	RTE_ETH_VALID_PORTID_OR_RET(port_id);
>   	dev = &rte_eth_devices[port_id];
> @@ -1372,6 +1373,10 @@ rte_eth_dev_close(uint16_t port_id)
>   	dev->data->nb_tx_queues = 0;
>   	rte_free(dev->data->tx_queues);
>   	dev->data->tx_queues = NULL;
> +
> +	rte_free(dev->data->dev_private);
> +
> +	rte_eth_dev_release_port(dev);
>   }
>   
>   int
> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index 7070e9ab4..37a757a7a 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1797,8 +1797,9 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
>   
>   /**
>    * Close a stopped Ethernet device. The device cannot be restarted!
> - * The function frees all resources except for needed by the
> - * closed state. To free these resources, call rte_eth_dev_detach().
> + * The function frees all port resources.
> + * If there is no more port associated with the underlying device,
> + * the driver should free the device resources.
>    *
>    * @param port_id
>    *   The port identifier of the Ethernet device.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [RFC] ethdev: complete closing to free all resources
  2018-09-10  8:03 ` Andrew Rybchenko
@ 2018-09-10  8:42   ` Thomas Monjalon
  2018-09-10  8:54     ` Andrew Rybchenko
  0 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-09-10  8:42 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev

10/09/2018 10:03, Andrew Rybchenko:
> On 09/08/2018 02:39 AM, Thomas Monjalon wrote:
> > After closing a port, it cannot be restarted.
> > So there is no reason to not free all associated resources.
> >
> > The last step was done with rte_eth_dev_detach() which is deprecated.
> > Instead of removing the associated rte_device, the driver should check
> > if no more port (ethdev, cryptodev, etc) is still open for the device.
> > Then the device resources can be freed by the driver inside the
> > dev_close() driver callback operation.
> >
> > The last ethdev freeing (dev_private and final release), which were done
> > by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
> 
> For me, it sounds more logical to kill dev_close and keep detach.
> IMHO, dev_close is artificial and hardly useful. detach is a local pair 
> to attach.

I don't get your point.

In order to free a port, we need close + detach.
We can keep only one.
I choose close because:
	1) attach/detach are deprecated
	2) probe/close is a more obvious pair
	3) we need the driver to free the lower level resources

> Anyway it requires update of all drivers as I understand.

Yes if we want to free all resources.
But close operation in drivers can be completed in later steps.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [RFC] ethdev: complete closing to free all resources
  2018-09-10  8:42   ` Thomas Monjalon
@ 2018-09-10  8:54     ` Andrew Rybchenko
  2018-09-12 14:57       ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-09-10  8:54 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: ferruh.yigit, dev

On 09/10/2018 11:42 AM, Thomas Monjalon wrote:
> 10/09/2018 10:03, Andrew Rybchenko:
>> On 09/08/2018 02:39 AM, Thomas Monjalon wrote:
>>> After closing a port, it cannot be restarted.
>>> So there is no reason to not free all associated resources.
>>>
>>> The last step was done with rte_eth_dev_detach() which is deprecated.
>>> Instead of removing the associated rte_device, the driver should check
>>> if no more port (ethdev, cryptodev, etc) is still open for the device.
>>> Then the device resources can be freed by the driver inside the
>>> dev_close() driver callback operation.
>>>
>>> The last ethdev freeing (dev_private and final release), which were done
>>> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
>> For me, it sounds more logical to kill dev_close and keep detach.
>> IMHO, dev_close is artificial and hardly useful. detach is a local pair
>> to attach.
> I don't get your point.
>
> In order to free a port, we need close + detach.
> We can keep only one.
> I choose close because:
> 	1) attach/detach are deprecated
> 	2) probe/close is a more obvious pair
> 	3) we need the driver to free the lower level resources

Yes, I'm sorry I used bad terminology.
We have probe/remove pair for both PCI and vdev drivers and I mean
that remove is a better candidate to be kept (as a pair for probe which
allocates all resources).

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [RFC] ethdev: complete closing to free all resources
  2018-09-10  8:54     ` Andrew Rybchenko
@ 2018-09-12 14:57       ` Thomas Monjalon
  2018-09-12 15:44         ` Andrew Rybchenko
  0 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-09-12 14:57 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev

10/09/2018 10:54, Andrew Rybchenko:
> On 09/10/2018 11:42 AM, Thomas Monjalon wrote:
> > 10/09/2018 10:03, Andrew Rybchenko:
> >> On 09/08/2018 02:39 AM, Thomas Monjalon wrote:
> >>> After closing a port, it cannot be restarted.
> >>> So there is no reason to not free all associated resources.
> >>>
> >>> The last step was done with rte_eth_dev_detach() which is deprecated.
> >>> Instead of removing the associated rte_device, the driver should check
> >>> if no more port (ethdev, cryptodev, etc) is still open for the device.
> >>> Then the device resources can be freed by the driver inside the
> >>> dev_close() driver callback operation.
> >>>
> >>> The last ethdev freeing (dev_private and final release), which were done
> >>> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
> >> For me, it sounds more logical to kill dev_close and keep detach.
> >> IMHO, dev_close is artificial and hardly useful. detach is a local pair
> >> to attach.
> > I don't get your point.
> >
> > In order to free a port, we need close + detach.
> > We can keep only one.
> > I choose close because:
> > 	1) attach/detach are deprecated
> > 	2) probe/close is a more obvious pair
> > 	3) we need the driver to free the lower level resources
> 
> Yes, I'm sorry I used bad terminology.
> We have probe/remove pair for both PCI and vdev drivers and I mean
> that remove is a better candidate to be kept (as a pair for probe which
> allocates all resources).

OK, yes probe/remove is the pair at EAL level.
But if we want to request removal at ethdev level, rte_eth_dev_close
is the function.

Note that there is no function to request creation of an ethdev port.
Adding a new port is done only by the PMD during probing (rte_bus level).

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [RFC] ethdev: complete closing to free all resources
  2018-09-12 14:57       ` Thomas Monjalon
@ 2018-09-12 15:44         ` Andrew Rybchenko
  0 siblings, 0 replies; 78+ messages in thread
From: Andrew Rybchenko @ 2018-09-12 15:44 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: ferruh.yigit, dev

On 09/12/2018 05:57 PM, Thomas Monjalon wrote:
> 10/09/2018 10:54, Andrew Rybchenko:
>> On 09/10/2018 11:42 AM, Thomas Monjalon wrote:
>>> 10/09/2018 10:03, Andrew Rybchenko:
>>>> On 09/08/2018 02:39 AM, Thomas Monjalon wrote:
>>>>> After closing a port, it cannot be restarted.
>>>>> So there is no reason to not free all associated resources.
>>>>>
>>>>> The last step was done with rte_eth_dev_detach() which is deprecated.
>>>>> Instead of removing the associated rte_device, the driver should check
>>>>> if no more port (ethdev, cryptodev, etc) is still open for the device.
>>>>> Then the device resources can be freed by the driver inside the
>>>>> dev_close() driver callback operation.
>>>>>
>>>>> The last ethdev freeing (dev_private and final release), which were done
>>>>> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
>>>> For me, it sounds more logical to kill dev_close and keep detach.
>>>> IMHO, dev_close is artificial and hardly useful. detach is a local pair
>>>> to attach.
>>> I don't get your point.
>>>
>>> In order to free a port, we need close + detach.
>>> We can keep only one.
>>> I choose close because:
>>> 	1) attach/detach are deprecated
>>> 	2) probe/close is a more obvious pair
>>> 	3) we need the driver to free the lower level resources
>> Yes, I'm sorry I used bad terminology.
>> We have probe/remove pair for both PCI and vdev drivers and I mean
>> that remove is a better candidate to be kept (as a pair for probe which
>> allocates all resources).
> OK, yes probe/remove is the pair at EAL level.
> But if we want to request removal at ethdev level, rte_eth_dev_close
> is the function.
>
> Note that there is no function to request creation of an ethdev port.
> Adding a new port is done only by the PMD during probing (rte_bus level).

The overall picture is too vague. May be it is simply incomplete looking
at the patch only. I understand that restructuring is required looking at
rte_eth_dev_destroy() (which is used by i40e and ixgbe drivers only) and
rte_eth_dev_pci_release() used by other PCI drivers.

Right now it looks symmetric at least on drivers level which provides
init callback to probe to do driver-specific job and uninit callback to
remove to free driver-specific resources.

I can't say if the patch is right or wrong direction since final design
is unclear.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [RFC] ethdev: complete closing to free all resources
  2018-09-07 23:39 [dpdk-dev] [RFC] ethdev: complete closing to free all resources Thomas Monjalon
  2018-09-10  8:03 ` Andrew Rybchenko
@ 2018-09-28 12:46 ` Ferruh Yigit
  2018-10-09 22:00   ` Thomas Monjalon
  2018-10-09 22:17 ` [dpdk-dev] [PATCH v2] ethdev: complete closing of port Thomas Monjalon
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 78+ messages in thread
From: Ferruh Yigit @ 2018-09-28 12:46 UTC (permalink / raw)
  To: Thomas Monjalon, arybchenko; +Cc: dev

On 9/8/2018 12:39 AM, Thomas Monjalon wrote:
> After closing a port, it cannot be restarted.
> So there is no reason to not free all associated resources.
> 
> The last step was done with rte_eth_dev_detach() which is deprecated.
> Instead of removing the associated rte_device, the driver should check
> if no more port (ethdev, cryptodev, etc) is still open for the device.
> Then the device resources can be freed by the driver inside the
> dev_close() driver callback operation.
> 
> The last ethdev freeing (dev_private and final release), which were done
> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
> 
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
> This patch contains only the change in the close function as RFC.
> 
> This idea was presented at Dublin during the "hotplug talk".
> ---
>  lib/librte_ethdev/rte_ethdev.c | 5 +++++
>  lib/librte_ethdev/rte_ethdev.h | 5 +++--
>  2 files changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index 4c3202505..071fcbd23 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -1358,6 +1358,7 @@ void
>  rte_eth_dev_close(uint16_t port_id)
>  {
>  	struct rte_eth_dev *dev;
> +	struct rte_bus *bus;
>  
>  	RTE_ETH_VALID_PORTID_OR_RET(port_id);
>  	dev = &rte_eth_devices[port_id];
> @@ -1372,6 +1373,10 @@ rte_eth_dev_close(uint16_t port_id)
>  	dev->data->nb_tx_queues = 0;
>  	rte_free(dev->data->tx_queues);
>  	dev->data->tx_queues = NULL;
> +
> +	rte_free(dev->data->dev_private);
> +
> +	rte_eth_dev_release_port(dev);

These already done in:
rte_eth_dev_pci_generic_remove()
	rte_eth_dev_pci_release()

Perhaps all content of rte_eth_dev_pci_release(), including above updates,
should move to rte_eth_dev_close() and rte_eth_dev_pci_generic_remove() call
rte_eth_dev_close() directly.


Just thinking aloud,

driver->probe() called when a new device added.
Application startup can be thought as all devices added one by one. [Perhaps
this can be change in the future to add devices only when explicitly stated]

driver->remove() called when device removed.
When application terminated this path not called at all, perhaps we need a way
to remove all devices one by one on exit.

eth_dev_close(), when eth_dev removed in ethdev layer but device is not removed
in eal level,

I think it make sense for eth_dev_close():
- It does more cleanup, free resources and port_id
- but it may need to do more clean up, like call uninit() and do more driver
internal clean up too, and clean up the hw.
- so call stack can be:
  driver->remove()
    rte_eth_dev_pci_generic_remove()
      eth_dev_close()
        dev_uninit() [driver unint function ]


Another question, after eth_dev_close() ethdev is not usable and not able to
restart it back. So why we need eth_dev_close() in addition to dev remove, why
not directly call rte_eth_dev_detach()?


>  }
>  
>  int
> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
> index 7070e9ab4..37a757a7a 100644
> --- a/lib/librte_ethdev/rte_ethdev.h
> +++ b/lib/librte_ethdev/rte_ethdev.h
> @@ -1797,8 +1797,9 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
>  
>  /**
>   * Close a stopped Ethernet device. The device cannot be restarted!
> - * The function frees all resources except for needed by the
> - * closed state. To free these resources, call rte_eth_dev_detach().
> + * The function frees all port resources.
> + * If there is no more port associated with the underlying device,
> + * the driver should free the device resources.
>   *
>   * @param port_id
>   *   The port identifier of the Ethernet device.
> 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [RFC] ethdev: complete closing to free all resources
  2018-09-28 12:46 ` Ferruh Yigit
@ 2018-10-09 22:00   ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-09 22:00 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, arybchenko

28/09/2018 14:46, Ferruh Yigit:
> On 9/8/2018 12:39 AM, Thomas Monjalon wrote:
> > After closing a port, it cannot be restarted.
> > So there is no reason to not free all associated resources.
> > 
> > The last step was done with rte_eth_dev_detach() which is deprecated.
> > Instead of removing the associated rte_device, the driver should check
> > if no more port (ethdev, cryptodev, etc) is still open for the device.
> > Then the device resources can be freed by the driver inside the
> > dev_close() driver callback operation.
> > 
> > The last ethdev freeing (dev_private and final release), which were done
> > by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
> > 
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > ---
> > This patch contains only the change in the close function as RFC.
> > 
> > This idea was presented at Dublin during the "hotplug talk".
> > ---
> > @@ -1372,6 +1373,10 @@ rte_eth_dev_close(uint16_t port_id)
> >  	dev->data->nb_tx_queues = 0;
> >  	rte_free(dev->data->tx_queues);
> >  	dev->data->tx_queues = NULL;
> > +
> > +	rte_free(dev->data->dev_private);
> > +
> > +	rte_eth_dev_release_port(dev);
> 
> These already done in:
> rte_eth_dev_pci_generic_remove()
> 	rte_eth_dev_pci_release()
> 
> Perhaps all content of rte_eth_dev_pci_release(), including above updates,
> should move to rte_eth_dev_close() and rte_eth_dev_pci_generic_remove() call
> rte_eth_dev_close() directly.

Yes I think it is the way to go:
	- when removing a rte_device, close all associated ports.
and the reverse can be done in addition:
	- when closing the last port of a rte_device, remove it.

> Just thinking aloud,
> 
> driver->probe() called when a new device added.
> Application startup can be thought as all devices added one by one. [Perhaps
> this can be change in the future to add devices only when explicitly stated]
> 
> driver->remove() called when device removed.
> When application terminated this path not called at all, perhaps we need a way
> to remove all devices one by one on exit.
> 
> eth_dev_close(), when eth_dev removed in ethdev layer but device is not removed
> in eal level,
> 
> I think it make sense for eth_dev_close():
> - It does more cleanup, free resources and port_id
> - but it may need to do more clean up, like call uninit() and do more driver
> internal clean up too, and clean up the hw.
> - so call stack can be:
>   driver->remove()
>     rte_eth_dev_pci_generic_remove()
>       eth_dev_close()
>         dev_uninit() [driver unint function ]
> 
> 
> Another question, after eth_dev_close() ethdev is not usable and not able to
> restart it back. So why we need eth_dev_close() in addition to dev remove, why
> not directly call rte_eth_dev_detach()?

rte_eth_dev_detach is assuming a 1:1 mapping between
EAL rte_device and rte_eth_dev port.
That's why it is deprecated and going to be removed.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v2] ethdev: complete closing of port
  2018-09-07 23:39 [dpdk-dev] [RFC] ethdev: complete closing to free all resources Thomas Monjalon
  2018-09-10  8:03 ` Andrew Rybchenko
  2018-09-28 12:46 ` Ferruh Yigit
@ 2018-10-09 22:17 ` Thomas Monjalon
  2018-10-10  6:15   ` Andrew Rybchenko
  2018-10-14 23:20 ` [dpdk-dev] [PATCH v3 0/2] ethdev port freeing Thomas Monjalon
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-09 22:17 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

After closing a port, it cannot be restarted.
So there is no reason to not free all associated resources.

The last step was done with rte_eth_dev_detach() which is deprecated.
Instead of blindly removing the associated rte_device, the driver should
check if no more port (ethdev, cryptodev, etc) is open for the device.

The last ethdev freeing (dev_private and final release), which were done
by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().

If the driver is trying to free the port again, the function
rte_eth_dev_release_port() will abort with -ENODEV error.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 lib/librte_ethdev/rte_ethdev.c | 6 ++++++
 lib/librte_ethdev/rte_ethdev.h | 3 +--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index ed83e5954..3062dc711 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -506,6 +506,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 {
 	if (eth_dev == NULL)
 		return -EINVAL;
+	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
+		return -ENODEV;
 
 	rte_eth_dev_shared_data_prepare();
 
@@ -1441,6 +1443,10 @@ rte_eth_dev_close(uint16_t port_id)
 	dev->data->nb_tx_queues = 0;
 	rte_free(dev->data->tx_queues);
 	dev->data->tx_queues = NULL;
+
+	rte_free(dev->data->dev_private);
+
+	rte_eth_dev_release_port(dev);
 }
 
 int
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index a8942ff88..378c01afa 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1846,8 +1846,7 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
 
 /**
  * Close a stopped Ethernet device. The device cannot be restarted!
- * The function frees all resources except for needed by the
- * closed state.
+ * The function frees all port resources.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v2] ethdev: complete closing of port
  2018-10-09 22:17 ` [dpdk-dev] [PATCH v2] ethdev: complete closing of port Thomas Monjalon
@ 2018-10-10  6:15   ` Andrew Rybchenko
  2018-10-10  7:44     ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-10  6:15 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit; +Cc: dev, ophirmu

On 10/10/18 1:17 AM, Thomas Monjalon wrote:
> After closing a port, it cannot be restarted.
> So there is no reason to not free all associated resources.
>
> The last step was done with rte_eth_dev_detach() which is deprecated.
> Instead of blindly removing the associated rte_device, the driver should
> check if no more port (ethdev, cryptodev, etc) is open for the device.
>
> The last ethdev freeing (dev_private and final release), which were done
> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
>
> If the driver is trying to free the port again, the function
> rte_eth_dev_release_port() will abort with -ENODEV error.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
>   lib/librte_ethdev/rte_ethdev.c | 6 ++++++
>   lib/librte_ethdev/rte_ethdev.h | 3 +--
>   2 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index ed83e5954..3062dc711 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -506,6 +506,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
>   {
>   	if (eth_dev == NULL)
>   		return -EINVAL;
> +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
> +		return -ENODEV;
>   
>   	rte_eth_dev_shared_data_prepare();
>   
> @@ -1441,6 +1443,10 @@ rte_eth_dev_close(uint16_t port_id)
>   	dev->data->nb_tx_queues = 0;
>   	rte_free(dev->data->tx_queues);
>   	dev->data->tx_queues = NULL;
> +
> +	rte_free(dev->data->dev_private);

It is used by, for example, PCI device uninit functions.
What does guarantee that uninit is done and we can free the private data.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v2] ethdev: complete closing of port
  2018-10-10  6:15   ` Andrew Rybchenko
@ 2018-10-10  7:44     ` Thomas Monjalon
  2018-10-10  7:50       ` Andrew Rybchenko
  0 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-10  7:44 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu

10/10/2018 08:15, Andrew Rybchenko:
> On 10/10/18 1:17 AM, Thomas Monjalon wrote:
> > After closing a port, it cannot be restarted.
> > So there is no reason to not free all associated resources.
> >
> > The last step was done with rte_eth_dev_detach() which is deprecated.
> > Instead of blindly removing the associated rte_device, the driver should
> > check if no more port (ethdev, cryptodev, etc) is open for the device.
> >
> > The last ethdev freeing (dev_private and final release), which were done
> > by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
> >
> > If the driver is trying to free the port again, the function
> > rte_eth_dev_release_port() will abort with -ENODEV error.
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > ---
> >   lib/librte_ethdev/rte_ethdev.c | 6 ++++++
> >   lib/librte_ethdev/rte_ethdev.h | 3 +--
> >   2 files changed, 7 insertions(+), 2 deletions(-)
> >
> > diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> > index ed83e5954..3062dc711 100644
> > --- a/lib/librte_ethdev/rte_ethdev.c
> > +++ b/lib/librte_ethdev/rte_ethdev.c
> > @@ -506,6 +506,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
> >   {
> >   	if (eth_dev == NULL)
> >   		return -EINVAL;
> > +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
> > +		return -ENODEV;
> >   
> >   	rte_eth_dev_shared_data_prepare();
> >   
> > @@ -1441,6 +1443,10 @@ rte_eth_dev_close(uint16_t port_id)
> >   	dev->data->nb_tx_queues = 0;
> >   	rte_free(dev->data->tx_queues);
> >   	dev->data->tx_queues = NULL;
> > +
> > +	rte_free(dev->data->dev_private);
> 
> It is used by, for example, PCI device uninit functions.
> What does guarantee that uninit is done and we can free the private data.

The state of the port is set to UNUSED and the name is NULL.
So nobody should try to use it anymore.
There are already some checks before calling uninit functions.
For instance, in rte_eth_dev_pci_generic_remove(),
rte_eth_dev_allocated() will return NULL and won't call uninit function.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v2] ethdev: complete closing of port
  2018-10-10  7:44     ` Thomas Monjalon
@ 2018-10-10  7:50       ` Andrew Rybchenko
  2018-10-10  8:39         ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-10  7:50 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: ferruh.yigit, dev, ophirmu

On 10/10/18 10:44 AM, Thomas Monjalon wrote:
> 10/10/2018 08:15, Andrew Rybchenko:
>> On 10/10/18 1:17 AM, Thomas Monjalon wrote:
>>> After closing a port, it cannot be restarted.
>>> So there is no reason to not free all associated resources.
>>>
>>> The last step was done with rte_eth_dev_detach() which is deprecated.
>>> Instead of blindly removing the associated rte_device, the driver should
>>> check if no more port (ethdev, cryptodev, etc) is open for the device.
>>>
>>> The last ethdev freeing (dev_private and final release), which were done
>>> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
>>>
>>> If the driver is trying to free the port again, the function
>>> rte_eth_dev_release_port() will abort with -ENODEV error.
>>>
>>> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
>>> ---
>>>    lib/librte_ethdev/rte_ethdev.c | 6 ++++++
>>>    lib/librte_ethdev/rte_ethdev.h | 3 +--
>>>    2 files changed, 7 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
>>> index ed83e5954..3062dc711 100644
>>> --- a/lib/librte_ethdev/rte_ethdev.c
>>> +++ b/lib/librte_ethdev/rte_ethdev.c
>>> @@ -506,6 +506,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
>>>    {
>>>    	if (eth_dev == NULL)
>>>    		return -EINVAL;
>>> +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
>>> +		return -ENODEV;
>>>    
>>>    	rte_eth_dev_shared_data_prepare();
>>>    
>>> @@ -1441,6 +1443,10 @@ rte_eth_dev_close(uint16_t port_id)
>>>    	dev->data->nb_tx_queues = 0;
>>>    	rte_free(dev->data->tx_queues);
>>>    	dev->data->tx_queues = NULL;
>>> +
>>> +	rte_free(dev->data->dev_private);
>> It is used by, for example, PCI device uninit functions.
>> What does guarantee that uninit is done and we can free the private data.
> The state of the port is set to UNUSED and the name is NULL.
> So nobody should try to use it anymore.
> There are already some checks before calling uninit functions.
> For instance, in rte_eth_dev_pci_generic_remove(),
> rte_eth_dev_allocated() will return NULL and won't call uninit function.

The questions are:
Is application allowed to call the function? When?
Who calls uninit in this case? (What does guarantee that uninit is done 
before close)

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v2] ethdev: complete closing of port
  2018-10-10  7:50       ` Andrew Rybchenko
@ 2018-10-10  8:39         ` Thomas Monjalon
  2018-10-10 15:01           ` Andrew Rybchenko
  0 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-10  8:39 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu

10/10/2018 09:50, Andrew Rybchenko:
> On 10/10/18 10:44 AM, Thomas Monjalon wrote:
> > 10/10/2018 08:15, Andrew Rybchenko:
> >> On 10/10/18 1:17 AM, Thomas Monjalon wrote:
> >>> After closing a port, it cannot be restarted.
> >>> So there is no reason to not free all associated resources.
> >>>
> >>> The last step was done with rte_eth_dev_detach() which is deprecated.
> >>> Instead of blindly removing the associated rte_device, the driver should
> >>> check if no more port (ethdev, cryptodev, etc) is open for the device.
> >>>
> >>> The last ethdev freeing (dev_private and final release), which were done
> >>> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
> >>>
> >>> If the driver is trying to free the port again, the function
> >>> rte_eth_dev_release_port() will abort with -ENODEV error.
> >>>
> >>> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> >>> ---
> >>>    lib/librte_ethdev/rte_ethdev.c | 6 ++++++
> >>>    lib/librte_ethdev/rte_ethdev.h | 3 +--
> >>>    2 files changed, 7 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> >>> index ed83e5954..3062dc711 100644
> >>> --- a/lib/librte_ethdev/rte_ethdev.c
> >>> +++ b/lib/librte_ethdev/rte_ethdev.c
> >>> @@ -506,6 +506,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
> >>>    {
> >>>    	if (eth_dev == NULL)
> >>>    		return -EINVAL;
> >>> +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
> >>> +		return -ENODEV;
> >>>    
> >>>    	rte_eth_dev_shared_data_prepare();
> >>>    
> >>> @@ -1441,6 +1443,10 @@ rte_eth_dev_close(uint16_t port_id)
> >>>    	dev->data->nb_tx_queues = 0;
> >>>    	rte_free(dev->data->tx_queues);
> >>>    	dev->data->tx_queues = NULL;
> >>> +
> >>> +	rte_free(dev->data->dev_private);
> >> It is used by, for example, PCI device uninit functions.
> >> What does guarantee that uninit is done and we can free the private data.
> > The state of the port is set to UNUSED and the name is NULL.
> > So nobody should try to use it anymore.
> > There are already some checks before calling uninit functions.
> > For instance, in rte_eth_dev_pci_generic_remove(),
> > rte_eth_dev_allocated() will return NULL and won't call uninit function.
> 
> The questions are:
> Is application allowed to call the function? When?
> Who calls uninit in this case? (What does guarantee that uninit is done 
> before close)

So far, everything is allowed:
	- The application can close a port and remove the rte_device later.
	- The application can remove the rte_device and expect the PMD is closing
		associated ports.

In other words, when rte_device is removed, the ports should be closed
by the PMD, except if the application has already closed the ports.
It means ethdev port close is optional, but EAL removal is always required.
The behaviour is not changed.

If we want to go further, we could change the behaviour of the close op,
by asking the PMD to remove the rte_device automatically if all associated
ports are closed. It would allow the application to manage only ports
at ethdev layer without bothering with low-level EAL management.
We can think about it as a planned change for next releases.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v2] ethdev: complete closing of port
  2018-10-10  8:39         ` Thomas Monjalon
@ 2018-10-10 15:01           ` Andrew Rybchenko
  2018-10-10 16:43             ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-10 15:01 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: ferruh.yigit, dev, ophirmu

On 10/10/18 11:39 AM, Thomas Monjalon wrote:
> 10/10/2018 09:50, Andrew Rybchenko:
>> On 10/10/18 10:44 AM, Thomas Monjalon wrote:
>>> 10/10/2018 08:15, Andrew Rybchenko:
>>>> On 10/10/18 1:17 AM, Thomas Monjalon wrote:
>>>>> After closing a port, it cannot be restarted.
>>>>> So there is no reason to not free all associated resources.
>>>>>
>>>>> The last step was done with rte_eth_dev_detach() which is deprecated.
>>>>> Instead of blindly removing the associated rte_device, the driver should
>>>>> check if no more port (ethdev, cryptodev, etc) is open for the device.
>>>>>
>>>>> The last ethdev freeing (dev_private and final release), which were done
>>>>> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
>>>>>
>>>>> If the driver is trying to free the port again, the function
>>>>> rte_eth_dev_release_port() will abort with -ENODEV error.
>>>>>
>>>>> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
>>>>> ---
>>>>>     lib/librte_ethdev/rte_ethdev.c | 6 ++++++
>>>>>     lib/librte_ethdev/rte_ethdev.h | 3 +--
>>>>>     2 files changed, 7 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
>>>>> index ed83e5954..3062dc711 100644
>>>>> --- a/lib/librte_ethdev/rte_ethdev.c
>>>>> +++ b/lib/librte_ethdev/rte_ethdev.c
>>>>> @@ -506,6 +506,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
>>>>>     {
>>>>>     	if (eth_dev == NULL)
>>>>>     		return -EINVAL;
>>>>> +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
>>>>> +		return -ENODEV;
>>>>>     
>>>>>     	rte_eth_dev_shared_data_prepare();
>>>>>     
>>>>> @@ -1441,6 +1443,10 @@ rte_eth_dev_close(uint16_t port_id)
>>>>>     	dev->data->nb_tx_queues = 0;
>>>>>     	rte_free(dev->data->tx_queues);
>>>>>     	dev->data->tx_queues = NULL;
>>>>> +
>>>>> +	rte_free(dev->data->dev_private);
>>>> It is used by, for example, PCI device uninit functions.
>>>> What does guarantee that uninit is done and we can free the private data.
>>> The state of the port is set to UNUSED and the name is NULL.
>>> So nobody should try to use it anymore.
>>> There are already some checks before calling uninit functions.
>>> For instance, in rte_eth_dev_pci_generic_remove(),
>>> rte_eth_dev_allocated() will return NULL and won't call uninit function.
>> The questions are:
>> Is application allowed to call the function? When?
>> Who calls uninit in this case? (What does guarantee that uninit is done
>> before close)
> So far, everything is allowed:
> 	- The application can close a port and remove the rte_device later.

If the patch is applied, close frees dev_private which is used by uninit.
So, uninit must be done first. Who does it?
(it looks like I'm missing something obvious, but still can't find it)

> 	- The application can remove the rte_device and expect the PMD is closing
> 		associated ports.
>
> In other words, when rte_device is removed, the ports should be closed
> by the PMD, except if the application has already closed the ports.
> It means ethdev port close is optional, but EAL removal is always required.
> The behaviour is not changed.
>
> If we want to go further, we could change the behaviour of the close op,
> by asking the PMD to remove the rte_device automatically if all associated
> ports are closed. It would allow the application to manage only ports
> at ethdev layer without bothering with low-level EAL management.
> We can think about it as a planned change for next releases.
>
>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v2] ethdev: complete closing of port
  2018-10-10 15:01           ` Andrew Rybchenko
@ 2018-10-10 16:43             ` Thomas Monjalon
  2018-10-10 18:01               ` Andrew Rybchenko
  0 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-10 16:43 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu

10/10/2018 17:01, Andrew Rybchenko:
> On 10/10/18 11:39 AM, Thomas Monjalon wrote:
> > 10/10/2018 09:50, Andrew Rybchenko:
> >> On 10/10/18 10:44 AM, Thomas Monjalon wrote:
> >>> 10/10/2018 08:15, Andrew Rybchenko:
> >>>> On 10/10/18 1:17 AM, Thomas Monjalon wrote:
> >>>>> After closing a port, it cannot be restarted.
> >>>>> So there is no reason to not free all associated resources.
> >>>>>
> >>>>> The last step was done with rte_eth_dev_detach() which is deprecated.
> >>>>> Instead of blindly removing the associated rte_device, the driver should
> >>>>> check if no more port (ethdev, cryptodev, etc) is open for the device.
> >>>>>
> >>>>> The last ethdev freeing (dev_private and final release), which were done
> >>>>> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
> >>>>>
> >>>>> If the driver is trying to free the port again, the function
> >>>>> rte_eth_dev_release_port() will abort with -ENODEV error.
> >>>>>
> >>>>> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> >>>>> ---
> >>>>>     lib/librte_ethdev/rte_ethdev.c | 6 ++++++
> >>>>>     lib/librte_ethdev/rte_ethdev.h | 3 +--
> >>>>>     2 files changed, 7 insertions(+), 2 deletions(-)
> >>>>>
> >>>>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> >>>>> index ed83e5954..3062dc711 100644
> >>>>> --- a/lib/librte_ethdev/rte_ethdev.c
> >>>>> +++ b/lib/librte_ethdev/rte_ethdev.c
> >>>>> @@ -506,6 +506,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
> >>>>>     {
> >>>>>     	if (eth_dev == NULL)
> >>>>>     		return -EINVAL;
> >>>>> +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
> >>>>> +		return -ENODEV;
> >>>>>     
> >>>>>     	rte_eth_dev_shared_data_prepare();
> >>>>>     
> >>>>> @@ -1441,6 +1443,10 @@ rte_eth_dev_close(uint16_t port_id)
> >>>>>     	dev->data->nb_tx_queues = 0;
> >>>>>     	rte_free(dev->data->tx_queues);
> >>>>>     	dev->data->tx_queues = NULL;
> >>>>> +
> >>>>> +	rte_free(dev->data->dev_private);
> >>>> 
> >>>> It is used by, for example, PCI device uninit functions.
> >>>> What does guarantee that uninit is done and we can free the private data.
> >>> 
> >>> The state of the port is set to UNUSED and the name is NULL.
> >>> So nobody should try to use it anymore.
> >>> There are already some checks before calling uninit functions.
> >>> For instance, in rte_eth_dev_pci_generic_remove(),
> >>> rte_eth_dev_allocated() will return NULL and won't call uninit function.
> >> 
> >> The questions are:
> >> Is application allowed to call the function? When?
> >> Who calls uninit in this case? (What does guarantee that uninit is done
> >> before close)
> > 
> > So far, everything is allowed:
> > 	- The application can close a port and remove the rte_device later.
> 
> If the patch is applied, close frees dev_private which is used by uninit.
> So, uninit must be done first. Who does it?
> (it looks like I'm missing something obvious, but still can't find it)

Yes, you missed my explanation above :)
Let me try again:

rte_eth_dev_release_port() does 3 things:
	- RTE_ETH_EVENT_DESTROY notification
	- state = RTE_ETH_DEV_UNUSED
	- memset data to 0

Because of state == RTE_ETH_DEV_UNUSED and data->name == NULL,
you should not try to use data->dev_private.
Before calling uninit function, the dev is retrieved by name:

    ethdev = rte_eth_dev_allocated(ethdev->data->name);
    if (!ethdev)
        return -ENODEV;

In our case, it will be -ENODEV, which is a good return when trying
to release a closed port.

Now I am thinking that PMDs could ignore this -ENODEV error:
it is OK to free the rte_device with ethdev port already closed.


> > 	- The application can remove the rte_device and expect the PMD is closing
> > 		associated ports.
> >
> > In other words, when rte_device is removed, the ports should be closed
> > by the PMD, except if the application has already closed the ports.
> > It means ethdev port close is optional, but EAL removal is always required.
> > The behaviour is not changed.
> >
> > If we want to go further, we could change the behaviour of the close op,
> > by asking the PMD to remove the rte_device automatically if all associated
> > ports are closed. It would allow the application to manage only ports
> > at ethdev layer without bothering with low-level EAL management.
> > We can think about it as a planned change for next releases.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v2] ethdev: complete closing of port
  2018-10-10 16:43             ` Thomas Monjalon
@ 2018-10-10 18:01               ` Andrew Rybchenko
  2018-10-10 19:03                 ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-10 18:01 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: ferruh.yigit, dev, ophirmu

On 10.10.2018 19:43, Thomas Monjalon wrote:
> 10/10/2018 17:01, Andrew Rybchenko:
>> On 10/10/18 11:39 AM, Thomas Monjalon wrote:
>>> 10/10/2018 09:50, Andrew Rybchenko:
>>>> On 10/10/18 10:44 AM, Thomas Monjalon wrote:
>>>>> 10/10/2018 08:15, Andrew Rybchenko:
>>>>>> On 10/10/18 1:17 AM, Thomas Monjalon wrote:
>>>>>>> After closing a port, it cannot be restarted.
>>>>>>> So there is no reason to not free all associated resources.
>>>>>>>
>>>>>>> The last step was done with rte_eth_dev_detach() which is deprecated.
>>>>>>> Instead of blindly removing the associated rte_device, the driver should
>>>>>>> check if no more port (ethdev, cryptodev, etc) is open for the device.
>>>>>>>
>>>>>>> The last ethdev freeing (dev_private and final release), which were done
>>>>>>> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
>>>>>>>
>>>>>>> If the driver is trying to free the port again, the function
>>>>>>> rte_eth_dev_release_port() will abort with -ENODEV error.
>>>>>>>
>>>>>>> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
>>>>>>> ---
>>>>>>>      lib/librte_ethdev/rte_ethdev.c | 6 ++++++
>>>>>>>      lib/librte_ethdev/rte_ethdev.h | 3 +--
>>>>>>>      2 files changed, 7 insertions(+), 2 deletions(-)
>>>>>>>
>>>>>>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
>>>>>>> index ed83e5954..3062dc711 100644
>>>>>>> --- a/lib/librte_ethdev/rte_ethdev.c
>>>>>>> +++ b/lib/librte_ethdev/rte_ethdev.c
>>>>>>> @@ -506,6 +506,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
>>>>>>>      {
>>>>>>>      	if (eth_dev == NULL)
>>>>>>>      		return -EINVAL;
>>>>>>> +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
>>>>>>> +		return -ENODEV;
>>>>>>>      
>>>>>>>      	rte_eth_dev_shared_data_prepare();
>>>>>>>      
>>>>>>> @@ -1441,6 +1443,10 @@ rte_eth_dev_close(uint16_t port_id)
>>>>>>>      	dev->data->nb_tx_queues = 0;
>>>>>>>      	rte_free(dev->data->tx_queues);
>>>>>>>      	dev->data->tx_queues = NULL;
>>>>>>> +
>>>>>>> +	rte_free(dev->data->dev_private);
>>>>>> It is used by, for example, PCI device uninit functions.
>>>>>> What does guarantee that uninit is done and we can free the private data.
>>>>> The state of the port is set to UNUSED and the name is NULL.
>>>>> So nobody should try to use it anymore.
>>>>> There are already some checks before calling uninit functions.
>>>>> For instance, in rte_eth_dev_pci_generic_remove(),
>>>>> rte_eth_dev_allocated() will return NULL and won't call uninit function.
>>>> The questions are:
>>>> Is application allowed to call the function? When?
>>>> Who calls uninit in this case? (What does guarantee that uninit is done
>>>> before close)
>>> So far, everything is allowed:
>>> 	- The application can close a port and remove the rte_device later.
>> If the patch is applied, close frees dev_private which is used by uninit.
>> So, uninit must be done first. Who does it?
>> (it looks like I'm missing something obvious, but still can't find it)
> Yes, you missed my explanation above :)
> Let me try again:
>
> rte_eth_dev_release_port() does 3 things:
> 	- RTE_ETH_EVENT_DESTROY notification
> 	- state = RTE_ETH_DEV_UNUSED
> 	- memset data to 0
>
> Because of state == RTE_ETH_DEV_UNUSED and data->name == NULL,
> you should not try to use data->dev_private.
> Before calling uninit function, the dev is retrieved by name:
>
>      ethdev = rte_eth_dev_allocated(ethdev->data->name);
>      if (!ethdev)
>          return -ENODEV;
>
> In our case, it will be -ENODEV, which is a good return when trying
> to release a closed port.

Yes, it replies on the question why dev_uninit is not called
upon device removal after close. But it does not reply on
the question what does call dev_uninit before/during dev_close.

> Now I am thinking that PMDs could ignore this -ENODEV error:
> it is OK to free the rte_device with ethdev port already closed.

I'll apply all 4 patch series tomorrow, add printout to dev_uninit,
build, run testpmd, do close and check if printout appears.
I hope it will reply on my question. I'll come back when I do and
have results.

>>> 	- The application can remove the rte_device and expect the PMD is closing
>>> 		associated ports.
>>>
>>> In other words, when rte_device is removed, the ports should be closed
>>> by the PMD, except if the application has already closed the ports.
>>> It means ethdev port close is optional, but EAL removal is always required.
>>> The behaviour is not changed.
>>>
>>> If we want to go further, we could change the behaviour of the close op,
>>> by asking the PMD to remove the rte_device automatically if all associated
>>> ports are closed. It would allow the application to manage only ports
>>> at ethdev layer without bothering with low-level EAL management.
>>> We can think about it as a planned change for next releases.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v2] ethdev: complete closing of port
  2018-10-10 18:01               ` Andrew Rybchenko
@ 2018-10-10 19:03                 ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-10 19:03 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu

10/10/2018 20:01, Andrew Rybchenko:
> On 10.10.2018 19:43, Thomas Monjalon wrote:
> > 10/10/2018 17:01, Andrew Rybchenko:
> >> On 10/10/18 11:39 AM, Thomas Monjalon wrote:
> >>> 10/10/2018 09:50, Andrew Rybchenko:
> >>>> On 10/10/18 10:44 AM, Thomas Monjalon wrote:
> >>>>> 10/10/2018 08:15, Andrew Rybchenko:
> >>>>>> On 10/10/18 1:17 AM, Thomas Monjalon wrote:
> >>>>>>> After closing a port, it cannot be restarted.
> >>>>>>> So there is no reason to not free all associated resources.
> >>>>>>>
> >>>>>>> The last step was done with rte_eth_dev_detach() which is deprecated.
> >>>>>>> Instead of blindly removing the associated rte_device, the driver should
> >>>>>>> check if no more port (ethdev, cryptodev, etc) is open for the device.
> >>>>>>>
> >>>>>>> The last ethdev freeing (dev_private and final release), which were done
> >>>>>>> by rte_eth_dev_detach(), are now done at the end of rte_eth_dev_close().
> >>>>>>>
> >>>>>>> If the driver is trying to free the port again, the function
> >>>>>>> rte_eth_dev_release_port() will abort with -ENODEV error.
> >>>>>>>
> >>>>>>> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> >>>>>>> ---
> >>>>>>>      lib/librte_ethdev/rte_ethdev.c | 6 ++++++
> >>>>>>>      lib/librte_ethdev/rte_ethdev.h | 3 +--
> >>>>>>>      2 files changed, 7 insertions(+), 2 deletions(-)
> >>>>>>>
> >>>>>>> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> >>>>>>> index ed83e5954..3062dc711 100644
> >>>>>>> --- a/lib/librte_ethdev/rte_ethdev.c
> >>>>>>> +++ b/lib/librte_ethdev/rte_ethdev.c
> >>>>>>> @@ -506,6 +506,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
> >>>>>>>      {
> >>>>>>>      	if (eth_dev == NULL)
> >>>>>>>      		return -EINVAL;
> >>>>>>> +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
> >>>>>>> +		return -ENODEV;
> >>>>>>>      
> >>>>>>>      	rte_eth_dev_shared_data_prepare();
> >>>>>>>      
> >>>>>>> @@ -1441,6 +1443,10 @@ rte_eth_dev_close(uint16_t port_id)
> >>>>>>>      	dev->data->nb_tx_queues = 0;
> >>>>>>>      	rte_free(dev->data->tx_queues);
> >>>>>>>      	dev->data->tx_queues = NULL;
> >>>>>>> +
> >>>>>>> +	rte_free(dev->data->dev_private);
> >>>>>> It is used by, for example, PCI device uninit functions.
> >>>>>> What does guarantee that uninit is done and we can free the private data.
> >>>>> The state of the port is set to UNUSED and the name is NULL.
> >>>>> So nobody should try to use it anymore.
> >>>>> There are already some checks before calling uninit functions.
> >>>>> For instance, in rte_eth_dev_pci_generic_remove(),
> >>>>> rte_eth_dev_allocated() will return NULL and won't call uninit function.
> >>>> The questions are:
> >>>> Is application allowed to call the function? When?
> >>>> Who calls uninit in this case? (What does guarantee that uninit is done
> >>>> before close)
> >>> So far, everything is allowed:
> >>> 	- The application can close a port and remove the rte_device later.
> >> If the patch is applied, close frees dev_private which is used by uninit.
> >> So, uninit must be done first. Who does it?
> >> (it looks like I'm missing something obvious, but still can't find it)
> > Yes, you missed my explanation above :)
> > Let me try again:
> >
> > rte_eth_dev_release_port() does 3 things:
> > 	- RTE_ETH_EVENT_DESTROY notification
> > 	- state = RTE_ETH_DEV_UNUSED
> > 	- memset data to 0
> >
> > Because of state == RTE_ETH_DEV_UNUSED and data->name == NULL,
> > you should not try to use data->dev_private.
> > Before calling uninit function, the dev is retrieved by name:
> >
> >      ethdev = rte_eth_dev_allocated(ethdev->data->name);
> >      if (!ethdev)
> >          return -ENODEV;
> >
> > In our case, it will be -ENODEV, which is a good return when trying
> > to release a closed port.
> 
> Yes, it replies on the question why dev_uninit is not called
> upon device removal after close. But it does not reply on
> the question what does call dev_uninit before/during dev_close.

Maybe I don't understand your question correctly.
dev_uninit is not called during dev_close.
However, as suggested by Ferruh, it would be cleaner to call dev_close
instead of dev_uninit which should do the same thing.
Currently, most of the PMDs expect both dev_close and dev_uninit to be
called in order to completely free a port.

The call tree to reach dev_uninit is:
	[rte_eal_hotplug_remove]
		rte_dev_remove
			bus.unplug
				driver.remove
					for port not closed
						dev_uninit
					free rte_device resources

In a next step, I would suggest to drop dev_uninit,
and call dev_close instead.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v3 0/2] ethdev port freeing
  2018-09-07 23:39 [dpdk-dev] [RFC] ethdev: complete closing to free all resources Thomas Monjalon
                   ` (2 preceding siblings ...)
  2018-10-09 22:17 ` [dpdk-dev] [PATCH v2] ethdev: complete closing of port Thomas Monjalon
@ 2018-10-14 23:20 ` Thomas Monjalon
  2018-10-14 23:20   ` [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port Thomas Monjalon
  2018-10-14 23:20   ` [dpdk-dev] [PATCH v3 2/2] ethdev: complete closing of port Thomas Monjalon
  2018-10-17  1:54 ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Thomas Monjalon
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-14 23:20 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

The function rte_eth_dev_detach() is freeing a port and its underlying
rte_device object. The issue is that we may have several ports
associated to the same rte_device.

The right replacement is to free the port, and free the rte_device
if no more ports.
At ethdev level, the public function for port freeing is rte_eth_dev_close().
The only miss is rte_eth_dev_release_port() to free all port resources.


Changes in v3:
  - free queues, MAC addresses and private structure
    in rte_eth_dev_release_port.


Thomas Monjalon (2):
  ethdev: free all common data when releasing port
  ethdev: complete closing of port

 drivers/net/af_packet/rte_eth_af_packet.c |  2 --
 drivers/net/ark/ark_ethdev.c              |  1 -
 drivers/net/avf/avf_ethdev.c              |  3 ---
 drivers/net/avp/avp_ethdev.c              |  5 ----
 drivers/net/axgbe/axgbe_ethdev.c          |  3 ---
 drivers/net/bnxt/bnxt_ethdev.c            |  8 ------
 drivers/net/bonding/rte_eth_bond_pmd.c    |  7 +----
 drivers/net/cxgbe/cxgbe_main.c            | 16 ++----------
 drivers/net/cxgbe/cxgbevf_main.c          |  9 +------
 drivers/net/dpaa/dpaa_ethdev.c            | 10 -------
 drivers/net/dpaa2/dpaa2_ethdev.c          | 10 -------
 drivers/net/e1000/em_ethdev.c             |  3 ---
 drivers/net/e1000/igb_ethdev.c            |  6 -----
 drivers/net/enetc/enetc_ethdev.c          |  4 +--
 drivers/net/failsafe/failsafe.c           |  3 ---
 drivers/net/fm10k/fm10k_ethdev.c          |  8 ------
 drivers/net/i40e/i40e_ethdev.c            |  3 ---
 drivers/net/i40e/i40e_ethdev_vf.c         |  3 ---
 drivers/net/ixgbe/ixgbe_ethdev.c          |  9 -------
 drivers/net/kni/rte_eth_kni.c             |  2 --
 drivers/net/liquidio/lio_ethdev.c         |  3 ---
 drivers/net/mlx4/mlx4.c                   |  3 +--
 drivers/net/mlx5/mlx5.c                   |  5 +---
 drivers/net/mvneta/mvneta_ethdev.c        | 16 ++++--------
 drivers/net/mvpp2/mrvl_ethdev.c           | 16 ++++--------
 drivers/net/netvsc/hn_ethdev.c            | 11 --------
 drivers/net/null/rte_eth_null.c           |  2 --
 drivers/net/octeontx/octeontx_ethdev.c    | 29 ++++++++------------
 drivers/net/pcap/rte_eth_pcap.c           |  7 -----
 drivers/net/qede/qede_ethdev.c            |  5 ----
 drivers/net/ring/rte_eth_ring.c           |  4 ---
 drivers/net/sfc/sfc_ethdev.c              |  3 ---
 drivers/net/softnic/rte_eth_softnic.c     |  6 ++---
 drivers/net/szedata2/rte_eth_szedata2.c   |  1 -
 drivers/net/tap/rte_eth_tap.c             |  1 -
 drivers/net/vhost/rte_eth_vhost.c         | 13 +++------
 drivers/net/virtio/virtio_ethdev.c        |  3 ---
 drivers/net/virtio/virtio_user_ethdev.c   |  3 ---
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  3 ---
 lib/librte_ethdev/rte_ethdev.c            | 32 +++++++++--------------
 lib/librte_ethdev/rte_ethdev.h            |  3 +--
 lib/librte_ethdev/rte_ethdev_pci.h        | 11 --------
 42 files changed, 47 insertions(+), 248 deletions(-)

-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port
  2018-10-14 23:20 ` [dpdk-dev] [PATCH v3 0/2] ethdev port freeing Thomas Monjalon
@ 2018-10-14 23:20   ` Thomas Monjalon
  2018-10-16 11:16     ` Andrew Rybchenko
  2018-10-14 23:20   ` [dpdk-dev] [PATCH v3 2/2] ethdev: complete closing of port Thomas Monjalon
  1 sibling, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-14 23:20 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

This is a clean-up of common ethdev data freeing.
All data freeing are moved to rte_eth_dev_release_port()
and done only in case of primary process.

It is probably fixing some memory leaks for PMDs which were
not freeing all data.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/net/af_packet/rte_eth_af_packet.c |  2 --
 drivers/net/ark/ark_ethdev.c              |  1 -
 drivers/net/avf/avf_ethdev.c              |  3 ---
 drivers/net/avp/avp_ethdev.c              |  5 ----
 drivers/net/axgbe/axgbe_ethdev.c          |  3 ---
 drivers/net/bnxt/bnxt_ethdev.c            |  4 ----
 drivers/net/bonding/rte_eth_bond_pmd.c    |  7 +-----
 drivers/net/cxgbe/cxgbe_main.c            | 16 ++-----------
 drivers/net/cxgbe/cxgbevf_main.c          |  9 +------
 drivers/net/dpaa/dpaa_ethdev.c            | 10 --------
 drivers/net/dpaa2/dpaa2_ethdev.c          | 10 --------
 drivers/net/e1000/em_ethdev.c             |  3 ---
 drivers/net/e1000/igb_ethdev.c            |  6 -----
 drivers/net/enetc/enetc_ethdev.c          |  4 +---
 drivers/net/failsafe/failsafe.c           |  3 ---
 drivers/net/fm10k/fm10k_ethdev.c          |  8 -------
 drivers/net/i40e/i40e_ethdev.c            |  3 ---
 drivers/net/i40e/i40e_ethdev_vf.c         |  3 ---
 drivers/net/ixgbe/ixgbe_ethdev.c          |  9 -------
 drivers/net/kni/rte_eth_kni.c             |  2 --
 drivers/net/liquidio/lio_ethdev.c         |  3 ---
 drivers/net/mlx4/mlx4.c                   |  3 +--
 drivers/net/mlx5/mlx5.c                   |  5 +---
 drivers/net/mvneta/mvneta_ethdev.c        | 16 ++++---------
 drivers/net/mvpp2/mrvl_ethdev.c           | 16 ++++---------
 drivers/net/netvsc/hn_ethdev.c            | 11 ---------
 drivers/net/null/rte_eth_null.c           |  2 --
 drivers/net/octeontx/octeontx_ethdev.c    | 29 +++++++++--------------
 drivers/net/pcap/rte_eth_pcap.c           |  7 ------
 drivers/net/qede/qede_ethdev.c            |  5 ----
 drivers/net/ring/rte_eth_ring.c           |  4 ----
 drivers/net/sfc/sfc_ethdev.c              |  3 ---
 drivers/net/softnic/rte_eth_softnic.c     |  6 ++---
 drivers/net/szedata2/rte_eth_szedata2.c   |  1 -
 drivers/net/tap/rte_eth_tap.c             |  1 -
 drivers/net/vhost/rte_eth_vhost.c         |  9 +++----
 drivers/net/virtio/virtio_ethdev.c        |  3 ---
 drivers/net/virtio/virtio_user_ethdev.c   |  3 ---
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  3 ---
 lib/librte_ethdev/rte_ethdev.c            | 23 ++++++++----------
 lib/librte_ethdev/rte_ethdev_pci.h        | 11 ---------
 41 files changed, 43 insertions(+), 232 deletions(-)

diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index bc7daed5e..74073ecf6 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -994,8 +994,6 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	}
 	free(internals->if_name);
 
-	rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index 552ca01a6..70d62ec7f 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -506,7 +506,6 @@ eth_ark_dev_uninit(struct rte_eth_dev *dev)
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
-	rte_free(dev->data->mac_addrs);
 	return 0;
 }
 
diff --git a/drivers/net/avf/avf_ethdev.c b/drivers/net/avf/avf_ethdev.c
index e56d57c43..13eec1b45 100644
--- a/drivers/net/avf/avf_ethdev.c
+++ b/drivers/net/avf/avf_ethdev.c
@@ -1303,9 +1303,6 @@ avf_dev_uninit(struct rte_eth_dev *dev)
 	rte_free(vf->aq_resp);
 	vf->aq_resp = NULL;
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	if (vf->rss_lut) {
 		rte_free(vf->rss_lut);
 		vf->rss_lut = NULL;
diff --git a/drivers/net/avp/avp_ethdev.c b/drivers/net/avp/avp_ethdev.c
index 0f8ccb954..09388d05f 100644
--- a/drivers/net/avp/avp_ethdev.c
+++ b/drivers/net/avp/avp_ethdev.c
@@ -1036,11 +1036,6 @@ eth_avp_dev_uninit(struct rte_eth_dev *eth_dev)
 		return ret;
 	}
 
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index 4b84b50c0..e89c0ec2c 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -718,9 +718,6 @@ eth_axgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 		return 0;
 
 	pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
-	/*Free macaddres*/
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 858e65d00..ff41cb0fa 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -3501,10 +3501,6 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev)
 	bnxt_disable_int(bp);
 	bnxt_free_int(bp);
 	bnxt_free_mem(bp);
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
 	if (bp->grp_info != NULL) {
 		rte_free(bp->grp_info);
 		bp->grp_info = NULL;
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 31c83a286..73da41862 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3128,10 +3128,7 @@ bond_alloc(struct rte_vdev_device *dev, uint8_t mode)
 
 err:
 	rte_free(internals);
-	if (eth_dev != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		rte_eth_dev_release_port(eth_dev);
-	}
+	rte_eth_dev_release_port(eth_dev);
 	return -1;
 }
 
@@ -3290,8 +3287,6 @@ bond_remove(struct rte_vdev_device *dev)
 	rte_mempool_free(internals->mode6.mempool);
 	rte_bitmap_free(internals->vlan_filter_bmp);
 	rte_free(internals->vlan_filter_bmpmem);
-	rte_free(eth_dev->data->dev_private);
-	rte_free(eth_dev->data->mac_addrs);
 
 	rte_eth_dev_release_port(eth_dev);
 
diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
index a135df9c7..88dc851f8 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -1710,12 +1710,7 @@ void cxgbe_close(struct adapter *adapter)
 			if (pi->viid != 0)
 				t4_free_vi(adapter, adapter->mbox,
 					   adapter->pf, 0, pi->viid);
-			rte_free(pi->eth_dev->data->mac_addrs);
-			/* Skip first port since it'll be freed by DPDK stack */
-			if (i) {
-				rte_free(pi->eth_dev->data->dev_private);
-				rte_eth_dev_release_port(pi->eth_dev);
-			}
+			rte_eth_dev_release_port(pi->eth_dev);
 		}
 		adapter->flags &= ~FULL_INIT_DONE;
 	}
@@ -1918,14 +1913,7 @@ int cxgbe_probe(struct adapter *adapter)
 		if (pi->viid != 0)
 			t4_free_vi(adapter, adapter->mbox, adapter->pf,
 				   0, pi->viid);
-		/* Skip first port since it'll be de-allocated by DPDK */
-		if (i == 0)
-			continue;
-		if (pi->eth_dev) {
-			if (pi->eth_dev->data->dev_private)
-				rte_free(pi->eth_dev->data->dev_private);
-			rte_eth_dev_release_port(pi->eth_dev);
-		}
+		rte_eth_dev_release_port(pi->eth_dev);
 	}
 
 	if (adapter->flags & FW_OK)
diff --git a/drivers/net/cxgbe/cxgbevf_main.c b/drivers/net/cxgbe/cxgbevf_main.c
index 4214d0312..6223e1250 100644
--- a/drivers/net/cxgbe/cxgbevf_main.c
+++ b/drivers/net/cxgbe/cxgbevf_main.c
@@ -282,14 +282,7 @@ int cxgbevf_probe(struct adapter *adapter)
 		if (pi->viid != 0)
 			t4_free_vi(adapter, adapter->mbox, adapter->pf,
 				   0, pi->viid);
-		/* Skip first port since it'll be de-allocated by DPDK */
-		if (i == 0)
-			continue;
-		if (pi->eth_dev) {
-			if (pi->eth_dev->data->dev_private)
-				rte_free(pi->eth_dev->data->dev_private);
-			rte_eth_dev_release_port(pi->eth_dev);
-		}
+		rte_eth_dev_release_port(pi->eth_dev);
 	}
 	return -err;
 }
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 5c743c3c8..d0572b3d9 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1439,10 +1439,6 @@ dpaa_dev_uninit(struct rte_eth_dev *dev)
 	rte_free(dpaa_intf->tx_queues);
 	dpaa_intf->tx_queues = NULL;
 
-	/* free memory for storing MAC addresses */
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
@@ -1544,9 +1540,6 @@ rte_dpaa_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused,
 		return 0;
 	}
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 	return diag;
 }
@@ -1561,9 +1554,6 @@ rte_dpaa_remove(struct rte_dpaa_device *dpaa_dev)
 	eth_dev = dpaa_dev->eth_dev;
 	dpaa_dev_uninit(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 880034fcf..3c986ea19 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -1953,12 +1953,6 @@ dpaa2_dev_uninit(struct rte_eth_dev *eth_dev)
 		priv->rx_vq[0] = NULL;
 	}
 
-	/* free memory for storing MAC addresses */
-	if (eth_dev->data->mac_addrs) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
-
 	/* Close the device at underlying layer*/
 	ret = dpni_close(dpni, CMD_PRI_LOW, priv->token);
 	if (ret) {
@@ -2021,8 +2015,6 @@ rte_dpaa2_probe(struct rte_dpaa2_driver *dpaa2_drv,
 		return 0;
 	}
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 	return diag;
 }
@@ -2035,8 +2027,6 @@ rte_dpaa2_remove(struct rte_dpaa2_device *dpaa2_dev)
 	eth_dev = dpaa2_dev->eth_dev;
 	dpaa2_dev_uninit(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 28c153512..8230824e7 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -329,9 +329,6 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(intr_handle);
 	rte_intr_callback_unregister(intr_handle,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e542ef572..d9d29d22f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -917,9 +917,6 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* Reset any pending lock */
 	igb_reset_swfw_lock(hw);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* uninitialize PF if max_vfs not zero */
 	igb_pf_host_uninit(eth_dev);
 
@@ -1073,9 +1070,6 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(&pci_dev->intr_handle);
 	rte_intr_callback_unregister(&pci_dev->intr_handle,
diff --git a/drivers/net/enetc/enetc_ethdev.c b/drivers/net/enetc/enetc_ethdev.c
index 3ee7bb446..023fe7517 100644
--- a/drivers/net/enetc/enetc_ethdev.c
+++ b/drivers/net/enetc/enetc_ethdev.c
@@ -108,11 +108,9 @@ enetc_dev_init(struct rte_eth_dev *eth_dev)
 }
 
 static int
-enetc_dev_uninit(struct rte_eth_dev *eth_dev)
+enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused)
 {
 	PMD_INIT_FUNC_TRACE();
-	rte_free(eth_dev->data->mac_addrs);
-
 	return 0;
 }
 
diff --git a/drivers/net/failsafe/failsafe.c b/drivers/net/failsafe/failsafe.c
index c3999f026..04c9f1f71 100644
--- a/drivers/net/failsafe/failsafe.c
+++ b/drivers/net/failsafe/failsafe.c
@@ -280,7 +280,6 @@ fs_eth_dev_create(struct rte_vdev_device *vdev)
 free_subs:
 	fs_sub_device_free(dev);
 free_dev:
-	rte_free(PRIV(dev));
 	rte_eth_dev_release_port(dev);
 	return -1;
 }
@@ -304,8 +303,6 @@ fs_rte_eth_free(const char *name)
 	ret = pthread_mutex_destroy(&PRIV(dev)->hotplug_mutex);
 	if (ret)
 		ERROR("Error while destroying hotplug mutex");
-	rte_free(PRIV(dev)->mcast_addrs);
-	rte_free(PRIV(dev));
 	rte_eth_dev_release_port(dev);
 	return ret;
 }
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 46983e5df..bb7b906a9 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3234,14 +3234,6 @@ eth_fm10k_dev_uninit(struct rte_eth_dev *dev)
 			fm10k_dev_interrupt_handler_vf, (void *)dev);
 	}
 
-	/* free mac memory */
-	if (dev->data->mac_addrs) {
-		rte_free(dev->data->mac_addrs);
-		dev->data->mac_addrs = NULL;
-	}
-
-	memset(hw, 0, sizeof(*hw));
-
 	return 0;
 }
 
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index f7a685c8c..8a5c3c8fb 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1728,9 +1728,6 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	/* uninitialize pf host driver */
 	i40e_pf_host_uninit(dev);
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(intr_handle);
 
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index baa6cc58f..ed2fc1310 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1483,9 +1483,6 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
 		return -1;
 	}
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index c458bffc0..269595b73 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1337,12 +1337,6 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* uninitialize PF if max_vfs not zero */
 	ixgbe_pf_host_uninit(eth_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
-	rte_free(eth_dev->data->hash_mac_addrs);
-	eth_dev->data->hash_mac_addrs = NULL;
-
 	/* remove all the fdir filters & hash */
 	ixgbe_fdir_filter_uninit(eth_dev);
 
@@ -1722,9 +1716,6 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* Disable the interrupts for VF */
 	ixgbevf_intr_disable(eth_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	rte_intr_disable(intr_handle);
 	rte_intr_callback_unregister(intr_handle,
 				     ixgbevf_dev_interrupt_handler, eth_dev);
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 8a7015a0b..af395ac17 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -469,8 +469,6 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	internals = eth_dev->data->dev_private;
 	rte_kni_release(internals->kni);
 
-	rte_free(internals);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	is_kni_initialized--;
diff --git a/drivers/net/liquidio/lio_ethdev.c b/drivers/net/liquidio/lio_ethdev.c
index 93e89007a..6755585d9 100644
--- a/drivers/net/liquidio/lio_ethdev.c
+++ b/drivers/net/liquidio/lio_ethdev.c
@@ -2043,9 +2043,6 @@ lio_eth_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* lio_free_sc_buffer_pool */
 	lio_free_sc_buffer_pool(lio_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 3de7bc53e..857b43fd8 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -785,8 +785,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			claim_zero(mlx4_glue->dealloc_pd(pd));
 		if (ctx)
 			claim_zero(mlx4_glue->close_device(ctx));
-		if (eth_dev)
-			rte_eth_dev_release_port(eth_dev);
+		rte_eth_dev_release_port(eth_dev);
 		break;
 	}
 	/*
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 8cbfee1ba..3c5cf78e4 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1226,8 +1226,7 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 	}
 	if (pd)
 		claim_zero(mlx5_glue->dealloc_pd(pd));
-	if (eth_dev)
-		rte_eth_dev_release_port(eth_dev);
+	rte_eth_dev_release_port(eth_dev);
 	if (ctx)
 		claim_zero(mlx5_glue->close_device(ctx));
 	assert(err > 0);
@@ -1447,8 +1446,6 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 			if (!list[i].eth_dev)
 				continue;
 			mlx5_dev_close(list[i].eth_dev);
-			if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-				rte_free(list[i].eth_dev->data->dev_private);
 			claim_zero(rte_eth_dev_release_port(list[i].eth_dev));
 		}
 		/* Restore original error. */
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index f7071bc2e..2d7666454 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -787,8 +787,9 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	priv = rte_zmalloc_socket(name, sizeof(*priv), 0, rte_socket_id());
 	if (!priv) {
 		ret = -ENOMEM;
-		goto out_free_dev;
+		goto out_free;
 	}
+	eth_dev->data->dev_private = priv;
 
 	eth_dev->data->mac_addrs =
 		rte_zmalloc("mac_addrs",
@@ -796,20 +797,19 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	if (!eth_dev->data->mac_addrs) {
 		MVNETA_LOG(ERR, "Failed to allocate space for eth addrs");
 		ret = -ENOMEM;
-		goto out_free_priv;
+		goto out_free;
 	}
 
 	memset(&req, 0, sizeof(req));
 	strcpy(req.ifr_name, name);
 	ret = ioctl(fd, SIOCGIFHWADDR, &req);
 	if (ret)
-		goto out_free_mac;
+		goto out_free;
 
 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
 
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
-	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
 	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
 	mvneta_set_tx_function(eth_dev);
@@ -817,11 +817,7 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 
 	rte_eth_dev_probing_finish(eth_dev);
 	return 0;
-out_free_mac:
-	rte_free(eth_dev->data->mac_addrs);
-out_free_priv:
-	rte_free(priv);
-out_free_dev:
+out_free:
 	rte_eth_dev_release_port(eth_dev);
 
 	return ret;
@@ -836,8 +832,6 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 static void
 mvneta_eth_dev_destroy(struct rte_eth_dev *eth_dev)
 {
-	rte_free(eth_dev->data->dev_private);
-	rte_free(eth_dev->data->mac_addrs);
 	rte_eth_dev_release_port(eth_dev);
 }
 
diff --git a/drivers/net/mvpp2/mrvl_ethdev.c b/drivers/net/mvpp2/mrvl_ethdev.c
index 0682c635a..ab4c14e51 100644
--- a/drivers/net/mvpp2/mrvl_ethdev.c
+++ b/drivers/net/mvpp2/mrvl_ethdev.c
@@ -2780,8 +2780,9 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	priv = mrvl_priv_create(name);
 	if (!priv) {
 		ret = -ENOMEM;
-		goto out_free_dev;
+		goto out_free;
 	}
+	eth_dev->data->dev_private = priv;
 
 	eth_dev->data->mac_addrs =
 		rte_zmalloc("mac_addrs",
@@ -2789,20 +2790,19 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	if (!eth_dev->data->mac_addrs) {
 		MRVL_LOG(ERR, "Failed to allocate space for eth addrs");
 		ret = -ENOMEM;
-		goto out_free_priv;
+		goto out_free;
 	}
 
 	memset(&req, 0, sizeof(req));
 	strcpy(req.ifr_name, name);
 	ret = ioctl(fd, SIOCGIFHWADDR, &req);
 	if (ret)
-		goto out_free_mac;
+		goto out_free;
 
 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
 
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
-	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
 	eth_dev->rx_pkt_burst = mrvl_rx_pkt_burst;
 	mrvl_set_tx_function(eth_dev);
@@ -2810,12 +2810,8 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 
 	rte_eth_dev_probing_finish(eth_dev);
 	return 0;
-out_free_mac:
-	rte_free(eth_dev->data->mac_addrs);
-out_free_dev:
+out_free:
 	rte_eth_dev_release_port(eth_dev);
-out_free_priv:
-	rte_free(priv);
 
 	return ret;
 }
@@ -2839,8 +2835,6 @@ mrvl_eth_dev_destroy(const char *name)
 	priv = eth_dev->data->dev_private;
 	pp2_bpool_deinit(priv->bpool);
 	used_bpools[priv->pp_id] &= ~(1 << priv->bpool_bit);
-	rte_free(priv);
-	rte_free(eth_dev->data->mac_addrs);
 	rte_eth_dev_release_port(eth_dev);
 }
 
diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c
index 8e728d639..323bc1262 100644
--- a/drivers/net/netvsc/hn_ethdev.c
+++ b/drivers/net/netvsc/hn_ethdev.c
@@ -121,17 +121,6 @@ eth_dev_vmbus_release(struct rte_eth_dev *eth_dev)
 	/* free ether device */
 	rte_eth_dev_release_port(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
-	eth_dev->data->dev_private = NULL;
-
-	/*
-	 * Secondary process will check the name to attach.
-	 * Clear this field to avoid attaching a released ports.
-	 */
-	eth_dev->data->name[0] = '\0';
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 }
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index de10b5bdf..3c51810ff 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -680,8 +680,6 @@ rte_pmd_null_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
-	rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index 71843c63a..e0619296f 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -1015,12 +1015,22 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 		return 0;
 	}
 
+	/* Reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(octtx_name);
+	if (eth_dev == NULL) {
+		octeontx_log_err("failed to allocate rte_eth_dev");
+		res = -ENOMEM;
+		goto err;
+	}
+	data = eth_dev->data;
+
 	nic = rte_zmalloc_socket(octtx_name, sizeof(*nic), 0, socket_id);
 	if (nic == NULL) {
 		octeontx_log_err("failed to allocate nic structure");
 		res = -ENOMEM;
 		goto err;
 	}
+	data->dev_private = nic;
 
 	nic->port_id = port;
 	nic->evdev = evdev;
@@ -1037,21 +1047,11 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 		goto err;
 	}
 
-	/* Reserve an ethdev entry */
-	eth_dev = rte_eth_dev_allocate(octtx_name);
-	if (eth_dev == NULL) {
-		octeontx_log_err("failed to allocate rte_eth_dev");
-		res = -ENOMEM;
-		goto err;
-	}
-
 	eth_dev->device = &dev->device;
 	eth_dev->intr_handle = NULL;
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->numa_node = dev->device.numa_node;
 
-	data = eth_dev->data;
-	data->dev_private = nic;
 	data->port_id = eth_dev->data->port_id;
 
 	nic->ev_queues = 1;
@@ -1103,12 +1103,7 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 	if (nic)
 		octeontx_port_close(nic);
 
-	if (eth_dev != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		rte_free(data);
-		rte_free(nic);
-		rte_eth_dev_release_port(eth_dev);
-	}
+	rte_eth_dev_release_port(eth_dev);
 
 	return res;
 }
@@ -1137,8 +1132,6 @@ octeontx_remove(struct rte_vdev_device *dev)
 		rte_event_dev_stop(nic->evdev);
 		PMD_INIT_LOG(INFO, "Closing octeontx device %s", octtx_name);
 
-		rte_free(eth_dev->data->mac_addrs);
-		rte_free(eth_dev->data->dev_private);
 		rte_eth_dev_release_port(eth_dev);
 		rte_event_dev_close(nic->evdev);
 	}
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 51d405116..8347ac2cf 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -1215,7 +1215,6 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
 static int
 pmd_pcap_remove(struct rte_vdev_device *dev)
 {
-	struct pmd_internals *internals = NULL;
 	struct rte_eth_dev *eth_dev = NULL;
 
 	PMD_LOG(INFO, "Closing pcap ethdev on numa socket %d",
@@ -1229,12 +1228,6 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
-	internals = eth_dev->data->dev_private;
-	if (internals && internals->phy_mac)
-		rte_free(eth_dev->data->mac_addrs);
-
-	rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 18d244a93..404859426 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2666,11 +2666,6 @@ static int qede_dev_common_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	if (eth_dev->data->mac_addrs)
-		rte_free(eth_dev->data->mac_addrs);
-
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/ring/rte_eth_ring.c b/drivers/net/ring/rte_eth_ring.c
index bfe2f1780..383fb782b 100644
--- a/drivers/net/ring/rte_eth_ring.c
+++ b/drivers/net/ring/rte_eth_ring.c
@@ -666,10 +666,6 @@ rte_pmd_ring_remove(struct rte_vdev_device *dev)
 		}
 	}
 
-	rte_free(eth_dev->data->rx_queues);
-	rte_free(eth_dev->data->tx_queues);
-	rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 	return 0;
 }
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index b2e17f26e..3886daf7a 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -2035,9 +2035,6 @@ sfc_eth_dev_uninit(struct rte_eth_dev *dev)
 	sfc_detach(sa);
 	sfc_unprobe(sa);
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	sfc_kvargs_cleanup(sa);
 
 	sfc_adapter_unlock(sa);
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 0fd264e25..f01ed36b6 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -556,7 +556,6 @@ static int
 pmd_remove(struct rte_vdev_device *vdev)
 {
 	struct rte_eth_dev *dev = NULL;
-	struct pmd_internals *p;
 
 	if (!vdev)
 		return -EINVAL;
@@ -567,12 +566,11 @@ pmd_remove(struct rte_vdev_device *vdev)
 	dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
 	if (dev == NULL)
 		return -ENODEV;
-	p = dev->data->dev_private;
 
 	/* Free device data structures*/
-	rte_free(dev->data);
+	pmd_free(dev->data->dev_private);
+	dev->data->dev_private = NULL;
 	rte_eth_dev_release_port(dev);
-	pmd_free(p);
 
 	return 0;
 }
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index 4e5e01cf1..88448eff6 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1544,7 +1544,6 @@ rte_szedata2_eth_dev_uninit(struct rte_eth_dev *dev)
 	PMD_INIT_FUNC_TRACE();
 
 	free(internals->sze_dev_path);
-	rte_free(dev->data->mac_addrs);
 
 	PMD_DRV_LOG(INFO, "%s device %s successfully uninitialized",
 			RTE_STR(RTE_SZEDATA2_DRIVER_NAME), dev->data->name);
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index ad5ae988b..902a60847 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -2100,7 +2100,6 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	}
 
 	close(internals->ioctl_sock);
-	rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	if (internals->ka_fd != -1) {
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index aa6052221..986bf9633 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -1220,10 +1220,12 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internal));
 	if (eth_dev == NULL)
 		goto error;
+	data = eth_dev->data;
 
 	eth_addr = rte_zmalloc_socket(name, sizeof(*eth_addr), 0, numa_node);
 	if (eth_addr == NULL)
 		goto error;
+	data->mac_addrs = eth_addr;
 	*eth_addr = base_eth_addr;
 	eth_addr->addr_bytes[5] = eth_dev->data->port_id;
 
@@ -1253,13 +1255,11 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
 
-	data = eth_dev->data;
 	data->nb_rx_queues = queues;
 	data->nb_tx_queues = queues;
 	internal->max_queues = queues;
 	internal->vid = -1;
 	data->dev_link = pmd_link;
-	data->mac_addrs = eth_addr;
 	data->dev_flags = RTE_ETH_DEV_INTR_LSC;
 
 	eth_dev->dev_ops = &ops;
@@ -1291,10 +1291,7 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 		free(internal->dev_name);
 	}
 	rte_free(vring_state);
-	rte_free(eth_addr);
-	if (eth_dev)
-		rte_eth_dev_release_port(eth_dev);
-	rte_free(internal);
+	rte_eth_dev_release_port(eth_dev);
 	rte_free(list);
 
 	return -1;
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index b81df0a99..3b1bec9ba 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1706,9 +1706,6 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->tx_pkt_burst = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* reset interrupt callback  */
 	if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
 		rte_intr_callback_unregister(eth_dev->intr_handle,
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 525d16cab..420364b7a 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -422,7 +422,6 @@ virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev)
 	if (!dev) {
 		PMD_INIT_LOG(ERR, "malloc virtio_user_dev failed");
 		rte_eth_dev_release_port(eth_dev);
-		rte_free(hw);
 		return NULL;
 	}
 
@@ -449,7 +448,6 @@ virtio_user_eth_dev_free(struct rte_eth_dev *eth_dev)
 	struct virtio_hw *hw = data->dev_private;
 
 	rte_free(hw->virtio_user_dev);
-	rte_free(hw);
 	rte_eth_dev_release_port(eth_dev);
 }
 
@@ -662,7 +660,6 @@ virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 	dev = hw->virtio_user_dev;
 	virtio_user_dev_uninit(dev);
 
-	rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 78e5b7680..41bcd450a 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -368,9 +368,6 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->tx_pkt_burst = NULL;
 	eth_dev->tx_pkt_prepare = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 14fc7e328..178800a5b 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -376,7 +376,14 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 
 	eth_dev->state = RTE_ETH_DEV_UNUSED;
 
-	memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		rte_free(eth_dev->data->rx_queues);
+		rte_free(eth_dev->data->tx_queues);
+		rte_free(eth_dev->data->mac_addrs);
+		rte_free(eth_dev->data->hash_mac_addrs);
+		rte_free(eth_dev->data->dev_private);
+		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
+	}
 
 	rte_spinlock_unlock(&rte_eth_dev_shared_data->ownership_lock);
 
@@ -3517,7 +3524,7 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 			if (!ethdev->data->dev_private) {
 				RTE_LOG(ERR, EAL, "failed to allocate private data");
 				retval = -ENOMEM;
-				goto data_alloc_failed;
+				goto probe_failed;
 			}
 		}
 	} else {
@@ -3549,14 +3556,9 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 	rte_eth_dev_probing_finish(ethdev);
 
 	return retval;
-probe_failed:
-	/* free ports private data if primary process */
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(ethdev->data->dev_private);
 
-data_alloc_failed:
+probe_failed:
 	rte_eth_dev_release_port(ethdev);
-
 	return retval;
 }
 
@@ -3577,11 +3579,6 @@ rte_eth_dev_destroy(struct rte_eth_dev *ethdev,
 			return ret;
 	}
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(ethdev->data->dev_private);
-
-	ethdev->data->dev_private = NULL;
-
 	return rte_eth_dev_release_port(ethdev);
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev_pci.h b/lib/librte_ethdev/rte_ethdev_pci.h
index f652596f4..23257e986 100644
--- a/lib/librte_ethdev/rte_ethdev_pci.h
+++ b/lib/librte_ethdev/rte_ethdev_pci.h
@@ -135,17 +135,6 @@ rte_eth_dev_pci_allocate(struct rte_pci_device *dev, size_t private_data_size)
 static inline void
 rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev)
 {
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
-	eth_dev->data->dev_private = NULL;
-
-	/*
-	 * Secondary process will check the name to attach.
-	 * Clear this field to avoid attaching a released ports.
-	 */
-	eth_dev->data->name[0] = '\0';
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v3 2/2] ethdev: complete closing of port
  2018-10-14 23:20 ` [dpdk-dev] [PATCH v3 0/2] ethdev port freeing Thomas Monjalon
  2018-10-14 23:20   ` [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port Thomas Monjalon
@ 2018-10-14 23:20   ` Thomas Monjalon
  2018-10-16 11:24     ` Andrew Rybchenko
  1 sibling, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-14 23:20 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

After closing a port, it cannot be restarted.
So there is no reason to not free all associated resources.

The last step was done with rte_eth_dev_detach() which is deprecated.
Instead of blindly removing the associated rte_device, the driver should
check if no more port (ethdev, cryptodev, etc) is open for the device.

The last ethdev freeing which were done by rte_eth_dev_detach(),
are now done at the end of rte_eth_dev_close().

If the driver is trying to free the port again, the function
rte_eth_dev_release_port() will abort with -ENODEV error.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/net/bnxt/bnxt_ethdev.c    | 4 ----
 drivers/net/vhost/rte_eth_vhost.c | 4 ----
 lib/librte_ethdev/rte_ethdev.c    | 9 +++------
 lib/librte_ethdev/rte_ethdev.h    | 3 +--
 4 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index ff41cb0fa..183b40821 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -712,10 +712,6 @@ static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (bp->dev_stopped == 0)
 		bnxt_dev_stop_op(eth_dev);
 
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
 	if (bp->grp_info != NULL) {
 		rte_free(bp->grp_info);
 		bp->grp_info = NULL;
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 986bf9633..b9cefbbe5 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -998,12 +998,8 @@ eth_dev_close(struct rte_eth_dev *dev)
 		for (i = 0; i < dev->data->nb_tx_queues; i++)
 			rte_free(dev->data->tx_queues[i]);
 
-	rte_free(dev->data->mac_addrs);
 	free(internal->dev_name);
 	free(internal->iface_name);
-	rte_free(internal);
-
-	dev->data->dev_private = NULL;
 }
 
 static int
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 178800a5b..987ba5ab1 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -367,6 +367,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 {
 	if (eth_dev == NULL)
 		return -EINVAL;
+	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
+		return -ENODEV;
 
 	rte_eth_dev_shared_data_prepare();
 
@@ -1384,12 +1386,7 @@ rte_eth_dev_close(uint16_t port_id)
 	dev->data->dev_started = 0;
 	(*dev->dev_ops->dev_close)(dev);
 
-	dev->data->nb_rx_queues = 0;
-	rte_free(dev->data->rx_queues);
-	dev->data->rx_queues = NULL;
-	dev->data->nb_tx_queues = 0;
-	rte_free(dev->data->tx_queues);
-	dev->data->tx_queues = NULL;
+	rte_eth_dev_release_port(dev);
 }
 
 int
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index fb40c89e0..dcdeb184b 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1802,8 +1802,7 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
 
 /**
  * Close a stopped Ethernet device. The device cannot be restarted!
- * The function frees all resources except for needed by the
- * closed state. To free these resources, call rte_eth_dev_detach().
+ * The function frees all port resources.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port
  2018-10-14 23:20   ` [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port Thomas Monjalon
@ 2018-10-16 11:16     ` Andrew Rybchenko
  2018-10-16 12:22       ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-16 11:16 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit; +Cc: dev, ophirmu, Rahul Lakkireddy

On 10/15/18 2:20 AM, Thomas Monjalon wrote:
> This is a clean-up of common ethdev data freeing.
> All data freeing are moved to rte_eth_dev_release_port()
> and done only in case of primary process.
>
> It is probably fixing some memory leaks for PMDs which were
> not freeing all data.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

<...>

> diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
> index a135df9c7..88dc851f8 100644
> --- a/drivers/net/cxgbe/cxgbe_main.c
> +++ b/drivers/net/cxgbe/cxgbe_main.c
> @@ -1710,12 +1710,7 @@ void cxgbe_close(struct adapter *adapter)
>   			if (pi->viid != 0)
>   				t4_free_vi(adapter, adapter->mbox,
>   					   adapter->pf, 0, pi->viid);
> -			rte_free(pi->eth_dev->data->mac_addrs);
> -			/* Skip first port since it'll be freed by DPDK stack */
> -			if (i) {
> -				rte_free(pi->eth_dev->data->dev_private);
> -				rte_eth_dev_release_port(pi->eth_dev);
> -			}
> +			rte_eth_dev_release_port(pi->eth_dev);
>   		}
>   		adapter->flags &= ~FULL_INIT_DONE;
>   	}
> @@ -1918,14 +1913,7 @@ int cxgbe_probe(struct adapter *adapter)
>   		if (pi->viid != 0)
>   			t4_free_vi(adapter, adapter->mbox, adapter->pf,
>   				   0, pi->viid);
> -		/* Skip first port since it'll be de-allocated by DPDK */
> -		if (i == 0)
> -			continue;
> -		if (pi->eth_dev) {
> -			if (pi->eth_dev->data->dev_private)
> -				rte_free(pi->eth_dev->data->dev_private);
> -			rte_eth_dev_release_port(pi->eth_dev);
> -		}
> +		rte_eth_dev_release_port(pi->eth_dev);
>   	}
>   
>   	if (adapter->flags & FW_OK)
> diff --git a/drivers/net/cxgbe/cxgbevf_main.c b/drivers/net/cxgbe/cxgbevf_main.c
> index 4214d0312..6223e1250 100644
> --- a/drivers/net/cxgbe/cxgbevf_main.c
> +++ b/drivers/net/cxgbe/cxgbevf_main.c
> @@ -282,14 +282,7 @@ int cxgbevf_probe(struct adapter *adapter)
>   		if (pi->viid != 0)
>   			t4_free_vi(adapter, adapter->mbox, adapter->pf,
>   				   0, pi->viid);
> -		/* Skip first port since it'll be de-allocated by DPDK */
> -		if (i == 0)
> -			continue;
> -		if (pi->eth_dev) {
> -			if (pi->eth_dev->data->dev_private)
> -				rte_free(pi->eth_dev->data->dev_private);
> -			rte_eth_dev_release_port(pi->eth_dev);
> -		}
> +		rte_eth_dev_release_port(pi->eth_dev);
>   	}
>   	return -err;
>   }

Above changes looks frightening. I've add cxgbe maintainer in CC.


> diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
> index 0fd264e25..f01ed36b6 100644
> --- a/drivers/net/softnic/rte_eth_softnic.c
> +++ b/drivers/net/softnic/rte_eth_softnic.c
> @@ -556,7 +556,6 @@ static int
>   pmd_remove(struct rte_vdev_device *vdev)
>   {
>   	struct rte_eth_dev *dev = NULL;
> -	struct pmd_internals *p;
>   
>   	if (!vdev)
>   		return -EINVAL;
> @@ -567,12 +566,11 @@ pmd_remove(struct rte_vdev_device *vdev)
>   	dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
>   	if (dev == NULL)
>   		return -ENODEV;
> -	p = dev->data->dev_private;
>   
>   	/* Free device data structures*/
> -	rte_free(dev->data);
> +	pmd_free(dev->data->dev_private);
> +	dev->data->dev_private = NULL;
>   	rte_eth_dev_release_port(dev);
> -	pmd_free(p);
>   
>   	return 0;
>   }

The above basically violates approach used everywhere else. It is OK to 
go, but should be reconsidered.

> diff --git a/lib/librte_ethdev/rte_ethdev_pci.h b/lib/librte_ethdev/rte_ethdev_pci.h
> index f652596f4..23257e986 100644
> --- a/lib/librte_ethdev/rte_ethdev_pci.h
> +++ b/lib/librte_ethdev/rte_ethdev_pci.h
> @@ -135,17 +135,6 @@ rte_eth_dev_pci_allocate(struct rte_pci_device *dev, size_t private_data_size)
>   static inline void
>   rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev)
>   {
> -	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
> -		rte_free(eth_dev->data->dev_private);
> -
> -	eth_dev->data->dev_private = NULL;
> -
> -	/*
> -	 * Secondary process will check the name to attach.
> -	 * Clear this field to avoid attaching a released ports.
> -	 */
> -	eth_dev->data->name[0] = '\0';
> -
>   	eth_dev->device = NULL;
>   	eth_dev->intr_handle = NULL;

Not directly related to the patch, but I don't understand why does
rte_eth_dev_pci_release () exist? It does nothing PCI specific.
May be just for symmetry to rte_eth_dev_pci_allocate().
Why is intr_handle set to NULL above? Is it PCI specific?
It does not look so, since failsafe uses it.

In general it looks good, really big work, but ideally it should be
acked by cxgbe maintainer as well.

Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/2] ethdev: complete closing of port
  2018-10-14 23:20   ` [dpdk-dev] [PATCH v3 2/2] ethdev: complete closing of port Thomas Monjalon
@ 2018-10-16 11:24     ` Andrew Rybchenko
  2018-10-16 12:25       ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-16 11:24 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit; +Cc: dev, ophirmu

On 10/15/18 2:20 AM, Thomas Monjalon wrote:
> After closing a port, it cannot be restarted.
> So there is no reason to not free all associated resources.
>
> The last step was done with rte_eth_dev_detach() which is deprecated.
> Instead of blindly removing the associated rte_device, the driver should
> check if no more port (ethdev, cryptodev, etc) is open for the device.
>
> The last ethdev freeing which were done by rte_eth_dev_detach(),
> are now done at the end of rte_eth_dev_close().
>
> If the driver is trying to free the port again, the function
> rte_eth_dev_release_port() will abort with -ENODEV error.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
>   drivers/net/bnxt/bnxt_ethdev.c    | 4 ----
>   drivers/net/vhost/rte_eth_vhost.c | 4 ----
>   lib/librte_ethdev/rte_ethdev.c    | 9 +++------
>   lib/librte_ethdev/rte_ethdev.h    | 3 +--
>   4 files changed, 4 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
> index ff41cb0fa..183b40821 100644
> --- a/drivers/net/bnxt/bnxt_ethdev.c
> +++ b/drivers/net/bnxt/bnxt_ethdev.c
> @@ -712,10 +712,6 @@ static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
>   	if (bp->dev_stopped == 0)
>   		bnxt_dev_stop_op(eth_dev);
>   
> -	if (eth_dev->data->mac_addrs != NULL) {
> -		rte_free(eth_dev->data->mac_addrs);
> -		eth_dev->data->mac_addrs = NULL;
> -	}
>   	if (bp->grp_info != NULL) {
>   		rte_free(bp->grp_info);
>   		bp->grp_info = NULL;
> diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
> index 986bf9633..b9cefbbe5 100644
> --- a/drivers/net/vhost/rte_eth_vhost.c
> +++ b/drivers/net/vhost/rte_eth_vhost.c
> @@ -998,12 +998,8 @@ eth_dev_close(struct rte_eth_dev *dev)
>   		for (i = 0; i < dev->data->nb_tx_queues; i++)
>   			rte_free(dev->data->tx_queues[i]);
>   
> -	rte_free(dev->data->mac_addrs);
>   	free(internal->dev_name);
>   	free(internal->iface_name);
> -	rte_free(internal);
> -
> -	dev->data->dev_private = NULL;
>   }
>   
>   static int

It looks like above snippets should be a part of previous changeset.

> diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
> index 178800a5b..987ba5ab1 100644
> --- a/lib/librte_ethdev/rte_ethdev.c
> +++ b/lib/librte_ethdev/rte_ethdev.c
> @@ -367,6 +367,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
>   {
>   	if (eth_dev == NULL)
>   		return -EINVAL;
> +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
> +		return -ENODEV;
>   
>   	rte_eth_dev_shared_data_prepare();
>   
> @@ -1384,12 +1386,7 @@ rte_eth_dev_close(uint16_t port_id)
>   	dev->data->dev_started = 0;
>   	(*dev->dev_ops->dev_close)(dev);
>   
> -	dev->data->nb_rx_queues = 0;
> -	rte_free(dev->data->rx_queues);
> -	dev->data->rx_queues = NULL;
> -	dev->data->nb_tx_queues = 0;
> -	rte_free(dev->data->tx_queues);
> -	dev->data->tx_queues = NULL;
> +	rte_eth_dev_release_port(dev);
>   }
>   
>   int

Right now it introduces resource leak for resources which are
freed by PCI drivers in uninit.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port
  2018-10-16 11:16     ` Andrew Rybchenko
@ 2018-10-16 12:22       ` Thomas Monjalon
  2018-10-16 12:47         ` Andrew Rybchenko
  0 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-16 12:22 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu, Rahul Lakkireddy

16/10/2018 13:16, Andrew Rybchenko:
> On 10/15/18 2:20 AM, Thomas Monjalon wrote:
> > This is a clean-up of common ethdev data freeing.
> > All data freeing are moved to rte_eth_dev_release_port()
> > and done only in case of primary process.
> >
> > It is probably fixing some memory leaks for PMDs which were
> > not freeing all data.
[...]
> > --- a/drivers/net/softnic/rte_eth_softnic.c
> > +++ b/drivers/net/softnic/rte_eth_softnic.c
> > @@ -556,7 +556,6 @@ static int
> >   pmd_remove(struct rte_vdev_device *vdev)
> >   {
> >   	struct rte_eth_dev *dev = NULL;
> > -	struct pmd_internals *p;
> >   
> >   	if (!vdev)
> >   		return -EINVAL;
> > @@ -567,12 +566,11 @@ pmd_remove(struct rte_vdev_device *vdev)
> >   	dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
> >   	if (dev == NULL)
> >   		return -ENODEV;
> > -	p = dev->data->dev_private;
> >   
> >   	/* Free device data structures*/
> > -	rte_free(dev->data);
> > +	pmd_free(dev->data->dev_private);
> > +	dev->data->dev_private = NULL;
> >   	rte_eth_dev_release_port(dev);
> > -	pmd_free(p);
> >   
> >   	return 0;
> >   }
> 
> The above basically violates approach used everywhere else. It is OK to 
> go, but should be reconsidered.

Yes, it is because pmd_free does more than freeing just dev_private.

[...]
> Not directly related to the patch, but I don't understand why does
> rte_eth_dev_pci_release () exist? It does nothing PCI specific.
> May be just for symmetry to rte_eth_dev_pci_allocate().
> Why is intr_handle set to NULL above? Is it PCI specific?
> It does not look so, since failsafe uses it.

I agree that all these functions must be reconsidered and reworked.
We should consider a big cleanup in ethdev for 19.02.

> In general it looks good, really big work, but ideally it should be
> acked by cxgbe maintainer as well.

Actually, after more thoughts, I think this patch is not correct.
It is freeing MAC adresses in ethdev, even if there was no specific
allocation done for it in the PMD. Only the PMD can know what are the
memory blocks to free.
And it is the same for data->dev_private: are we sure it has been malloc'ed?
Are we sure it has not been allocated as part of a bigger block?
Historically, ethdev was freeing data->dev_private in some cases.
So maybe we can keep this assumption.
Or we can move all data freeing to the PMD?

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/2] ethdev: complete closing of port
  2018-10-16 11:24     ` Andrew Rybchenko
@ 2018-10-16 12:25       ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-16 12:25 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu

16/10/2018 13:24, Andrew Rybchenko:
> On 10/15/18 2:20 AM, Thomas Monjalon wrote:
> > After closing a port, it cannot be restarted.
> > So there is no reason to not free all associated resources.
> >
> > The last step was done with rte_eth_dev_detach() which is deprecated.
> > Instead of blindly removing the associated rte_device, the driver should
> > check if no more port (ethdev, cryptodev, etc) is open for the device.
> >
> > The last ethdev freeing which were done by rte_eth_dev_detach(),
> > are now done at the end of rte_eth_dev_close().
> >
> > If the driver is trying to free the port again, the function
> > rte_eth_dev_release_port() will abort with -ENODEV error.
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > ---
> >   drivers/net/bnxt/bnxt_ethdev.c    | 4 ----
> >   drivers/net/vhost/rte_eth_vhost.c | 4 ----
> >   lib/librte_ethdev/rte_ethdev.c    | 9 +++------
> >   lib/librte_ethdev/rte_ethdev.h    | 3 +--
> >   4 files changed, 4 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
> > index ff41cb0fa..183b40821 100644
> > --- a/drivers/net/bnxt/bnxt_ethdev.c
> > +++ b/drivers/net/bnxt/bnxt_ethdev.c
> > @@ -712,10 +712,6 @@ static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
> >   	if (bp->dev_stopped == 0)
> >   		bnxt_dev_stop_op(eth_dev);
> >   
> > -	if (eth_dev->data->mac_addrs != NULL) {
> > -		rte_free(eth_dev->data->mac_addrs);
> > -		eth_dev->data->mac_addrs = NULL;
> > -	}
> >   	if (bp->grp_info != NULL) {
> >   		rte_free(bp->grp_info);
> >   		bp->grp_info = NULL;
> > diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
> > index 986bf9633..b9cefbbe5 100644
> > --- a/drivers/net/vhost/rte_eth_vhost.c
> > +++ b/drivers/net/vhost/rte_eth_vhost.c
> > @@ -998,12 +998,8 @@ eth_dev_close(struct rte_eth_dev *dev)
> >   		for (i = 0; i < dev->data->nb_tx_queues; i++)
> >   			rte_free(dev->data->tx_queues[i]);
> >   
> > -	rte_free(dev->data->mac_addrs);
> >   	free(internal->dev_name);
> >   	free(internal->iface_name);
> > -	rte_free(internal);
> > -
> > -	dev->data->dev_private = NULL;
> >   }
> >   
> >   static int
> 
> It looks like above snippets should be a part of previous changeset.

No, this is related to close function.

> > --- a/lib/librte_ethdev/rte_ethdev.c
> > +++ b/lib/librte_ethdev/rte_ethdev.c
> > @@ -367,6 +367,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
> >   {
> >   	if (eth_dev == NULL)
> >   		return -EINVAL;
> > +	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
> > +		return -ENODEV;
> >   
> >   	rte_eth_dev_shared_data_prepare();
> >   
> > @@ -1384,12 +1386,7 @@ rte_eth_dev_close(uint16_t port_id)
> >   	dev->data->dev_started = 0;
> >   	(*dev->dev_ops->dev_close)(dev);
> >   
> > -	dev->data->nb_rx_queues = 0;
> > -	rte_free(dev->data->rx_queues);
> > -	dev->data->rx_queues = NULL;
> > -	dev->data->nb_tx_queues = 0;
> > -	rte_free(dev->data->tx_queues);
> > -	dev->data->tx_queues = NULL;
> > +	rte_eth_dev_release_port(dev);
> >   }
> >   
> >   int
> 
> Right now it introduces resource leak for resources which are
> freed by PCI drivers in uninit.

No, these resources are freed by rte_eth_dev_release_port.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port
  2018-10-16 12:22       ` Thomas Monjalon
@ 2018-10-16 12:47         ` Andrew Rybchenko
  2018-10-16 12:52           ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-16 12:47 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: ferruh.yigit, dev, ophirmu, Rahul Lakkireddy

On 10/16/18 3:22 PM, Thomas Monjalon wrote:
> 16/10/2018 13:16, Andrew Rybchenko:
>> On 10/15/18 2:20 AM, Thomas Monjalon wrote:
>>> This is a clean-up of common ethdev data freeing.
>>> All data freeing are moved to rte_eth_dev_release_port()
>>> and done only in case of primary process.
>>>
>>> It is probably fixing some memory leaks for PMDs which were
>>> not freeing all data.
> [...]
>> In general it looks good, really big work, but ideally it should be
>> acked by cxgbe maintainer as well.
> Actually, after more thoughts, I think this patch is not correct.
> It is freeing MAC adresses in ethdev, even if there was no specific
> allocation done for it in the PMD. Only the PMD can know what are the
> memory blocks to free.
> And it is the same for data->dev_private: are we sure it has been malloc'ed?
> Are we sure it has not been allocated as part of a bigger block?
> Historically, ethdev was freeing data->dev_private in some cases.
> So maybe we can keep this assumption.
> Or we can move all data freeing to the PMD?

It is allocated in rte_eth_dev_create(), rte_eth_vdev_allocate(),
rte_eth_dev_pci_allocate() and some PMDs. I can't say that I'm happy
with it, but it could be really required. May be it should be default
behaviour and if PMD wants override it, just free before and
set dev_private to NULL.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port
  2018-10-16 12:47         ` Andrew Rybchenko
@ 2018-10-16 12:52           ` Thomas Monjalon
  2018-10-16 12:55             ` Andrew Rybchenko
  0 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-16 12:52 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu, Rahul Lakkireddy

16/10/2018 14:47, Andrew Rybchenko:
> On 10/16/18 3:22 PM, Thomas Monjalon wrote:
> > 16/10/2018 13:16, Andrew Rybchenko:
> >> On 10/15/18 2:20 AM, Thomas Monjalon wrote:
> >>> This is a clean-up of common ethdev data freeing.
> >>> All data freeing are moved to rte_eth_dev_release_port()
> >>> and done only in case of primary process.
> >>>
> >>> It is probably fixing some memory leaks for PMDs which were
> >>> not freeing all data.
> > [...]
> >> In general it looks good, really big work, but ideally it should be
> >> acked by cxgbe maintainer as well.
> > Actually, after more thoughts, I think this patch is not correct.
> > It is freeing MAC adresses in ethdev, even if there was no specific
> > allocation done for it in the PMD. Only the PMD can know what are the
> > memory blocks to free.
> > And it is the same for data->dev_private: are we sure it has been malloc'ed?
> > Are we sure it has not been allocated as part of a bigger block?
> > Historically, ethdev was freeing data->dev_private in some cases.
> > So maybe we can keep this assumption.
> > Or we can move all data freeing to the PMD?
> 
> It is allocated in rte_eth_dev_create(), rte_eth_vdev_allocate(),
> rte_eth_dev_pci_allocate() and some PMDs. I can't say that I'm happy
> with it, but it could be really required. May be it should be default
> behaviour and if PMD wants override it, just free before and
> set dev_private to NULL.

Yes, you're right!
So freeing is done by default in rte_eth_dev_release_port(),
and PMD can avoid it by setting fields to NULL before calling it.

In this case, I just need to double check the MAC freeing,
and set NULL in some PMDs which do not allocate MAC separately.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port
  2018-10-16 12:52           ` Thomas Monjalon
@ 2018-10-16 12:55             ` Andrew Rybchenko
  0 siblings, 0 replies; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-16 12:55 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: ferruh.yigit, dev, ophirmu, Rahul Lakkireddy

On 10/16/18 3:52 PM, Thomas Monjalon wrote:
> 16/10/2018 14:47, Andrew Rybchenko:
>> On 10/16/18 3:22 PM, Thomas Monjalon wrote:
>>> 16/10/2018 13:16, Andrew Rybchenko:
>>>> On 10/15/18 2:20 AM, Thomas Monjalon wrote:
>>>>> This is a clean-up of common ethdev data freeing.
>>>>> All data freeing are moved to rte_eth_dev_release_port()
>>>>> and done only in case of primary process.
>>>>>
>>>>> It is probably fixing some memory leaks for PMDs which were
>>>>> not freeing all data.
>>> [...]
>>>> In general it looks good, really big work, but ideally it should be
>>>> acked by cxgbe maintainer as well.
>>> Actually, after more thoughts, I think this patch is not correct.
>>> It is freeing MAC adresses in ethdev, even if there was no specific
>>> allocation done for it in the PMD. Only the PMD can know what are the
>>> memory blocks to free.
>>> And it is the same for data->dev_private: are we sure it has been malloc'ed?
>>> Are we sure it has not been allocated as part of a bigger block?
>>> Historically, ethdev was freeing data->dev_private in some cases.
>>> So maybe we can keep this assumption.
>>> Or we can move all data freeing to the PMD?
>> It is allocated in rte_eth_dev_create(), rte_eth_vdev_allocate(),
>> rte_eth_dev_pci_allocate() and some PMDs. I can't say that I'm happy
>> with it, but it could be really required. May be it should be default
>> behaviour and if PMD wants override it, just free before and
>> set dev_private to NULL.
> Yes, you're right!
> So freeing is done by default in rte_eth_dev_release_port(),
> and PMD can avoid it by setting fields to NULL before calling it.
>
> In this case, I just need to double check the MAC freeing,
> and set NULL in some PMDs which do not allocate MAC separately.

One more thought that we should document it since it is
used by all PMDs and we have really a lot already and it looks
like every release cycle we have at least plus one.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v3 0/4] ethdev port freeing
  2018-09-07 23:39 [dpdk-dev] [RFC] ethdev: complete closing to free all resources Thomas Monjalon
                   ` (3 preceding siblings ...)
  2018-10-14 23:20 ` [dpdk-dev] [PATCH v3 0/2] ethdev port freeing Thomas Monjalon
@ 2018-10-17  1:54 ` Thomas Monjalon
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed Thomas Monjalon
                     ` (4 more replies)
  2018-10-18  1:23 ` [dpdk-dev] [PATCH v5 0/6] " Thomas Monjalon
  2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
  6 siblings, 5 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  1:54 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

The function rte_eth_dev_detach() is freeing a port and its underlying
rte_device object. The issue is that we may have several ports
associated to the same rte_device.

The right replacement is to free the port, and free the rte_device
if no more ports.
At ethdev level, the public function for port freeing is rte_eth_dev_close().
The only miss is rte_eth_dev_release_port() to free all port resources.

This patchset does a cleanup by moving as much ethdev data freeing
as possible in an unique function rte_eth_dev_release_port(),
and call this function in rte_eth_dev_close().


Changes in v4:
  - do not free data fields which are not dynamically allocated blocks
  - remove rte_eth_dev_release_port_secondary()
  - remove testpmd check to detach without closing

Changes in v3:
  - free queues, MAC addresses and private structure
    in rte_eth_dev_release_port.


Note: this patchset depends on multi-process hotplug series by Qi Zhang,
which is accepted but waiting for an unrelated DPAA compilation issue
to be fixed, before landing on master tree.


Thomas Monjalon (4):
  app/testpmd: allow detaching a port not closed
  ethdev: free all common data when releasing port
  ethdev: remove release function for secondary process
  ethdev: complete closing of port

 app/test-pmd/testpmd.c                    | 22 ++---------
 drivers/net/af_packet/rte_eth_af_packet.c | 11 ++++--
 drivers/net/ark/ark_ethdev.c              |  1 -
 drivers/net/avf/avf_ethdev.c              |  3 --
 drivers/net/avp/avp_ethdev.c              |  5 ---
 drivers/net/axgbe/axgbe_ethdev.c          |  3 --
 drivers/net/bnxt/bnxt_ethdev.c            |  8 ----
 drivers/net/bonding/rte_eth_bond_pmd.c    |  9 +----
 drivers/net/cxgbe/cxgbe_main.c            | 16 +-------
 drivers/net/cxgbe/cxgbevf_main.c          |  9 +----
 drivers/net/dpaa/dpaa_ethdev.c            | 10 -----
 drivers/net/dpaa2/dpaa2_ethdev.c          | 10 -----
 drivers/net/e1000/em_ethdev.c             |  3 --
 drivers/net/e1000/igb_ethdev.c            |  6 ---
 drivers/net/enetc/enetc_ethdev.c          |  4 +-
 drivers/net/failsafe/failsafe.c           |  6 ++-
 drivers/net/failsafe/failsafe_ops.c       |  2 +
 drivers/net/fm10k/fm10k_ethdev.c          |  8 ----
 drivers/net/i40e/i40e_ethdev.c            |  3 --
 drivers/net/i40e/i40e_ethdev_vf.c         |  3 --
 drivers/net/i40e/i40e_vf_representor.c    |  5 ++-
 drivers/net/ixgbe/ixgbe_ethdev.c          |  9 -----
 drivers/net/ixgbe/ixgbe_vf_representor.c  |  5 ++-
 drivers/net/kni/rte_eth_kni.c             |  7 ++--
 drivers/net/liquidio/lio_ethdev.c         |  3 --
 drivers/net/mlx4/mlx4.c                   |  7 +++-
 drivers/net/mlx5/mlx5.c                   | 11 ++++--
 drivers/net/mvneta/mvneta_ethdev.c        | 16 +++-----
 drivers/net/mvpp2/mrvl_ethdev.c           | 16 +++-----
 drivers/net/netvsc/hn_ethdev.c            | 20 +++-------
 drivers/net/null/rte_eth_null.c           |  7 +---
 drivers/net/octeontx/octeontx_ethdev.c    | 31 ++++++----------
 drivers/net/pcap/rte_eth_pcap.c           | 16 ++++----
 drivers/net/qede/qede_ethdev.c            |  5 ---
 drivers/net/ring/rte_eth_ring.c           |  6 +--
 drivers/net/sfc/sfc_ethdev.c              |  3 --
 drivers/net/softnic/rte_eth_softnic.c     | 10 ++---
 drivers/net/szedata2/rte_eth_szedata2.c   |  1 -
 drivers/net/tap/rte_eth_tap.c             | 11 +++++-
 drivers/net/vhost/rte_eth_vhost.c         | 15 ++------
 drivers/net/virtio/virtio_ethdev.c        |  3 --
 drivers/net/virtio/virtio_user_ethdev.c   |  3 --
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  3 --
 lib/librte_ethdev/rte_ethdev.c            | 45 +++++++----------------
 lib/librte_ethdev/rte_ethdev.h            |  3 +-
 lib/librte_ethdev/rte_ethdev_driver.h     | 25 +++++--------
 lib/librte_ethdev/rte_ethdev_pci.h        | 17 ---------
 lib/librte_ethdev/rte_ethdev_version.map  |  7 ----
 48 files changed, 129 insertions(+), 323 deletions(-)

-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed
  2018-10-17  1:54 ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Thomas Monjalon
@ 2018-10-17  1:54   ` Thomas Monjalon
  2018-10-17  2:06     ` Thomas Monjalon
  2018-10-17  6:26     ` Andrew Rybchenko
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 2/4] ethdev: free all common data when releasing port Thomas Monjalon
                     ` (3 subsequent siblings)
  4 siblings, 2 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  1:54 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

The testpmd application aim is for testing;
so order of operations should not be enforced.

There was a test to forbid detaching before closing a port.
However, it may interesting to test what happens in such case.
It is possible for a PMD to automatically close the port when detaching.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c | 22 ++++------------------
 1 file changed, 4 insertions(+), 18 deletions(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 5dbbf783f..f5dee1d71 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1938,18 +1938,6 @@ port_is_started(portid_t port_id)
 	return 1;
 }
 
-static int
-port_is_closed(portid_t port_id)
-{
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return 0;
-
-	if (ports[port_id].port_status != RTE_PORT_CLOSED)
-		return 0;
-
-	return 1;
-}
-
 int
 start_port(portid_t pid)
 {
@@ -2319,14 +2307,12 @@ detach_port(portid_t port_id)
 
 	printf("Detaching a port...\n");
 
-	if (!port_is_closed(port_id)) {
-		printf("Please close port first\n");
-		return;
+	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
+		printf("Port not closed\n");
+		if (ports[port_id].flow_list)
+			port_flow_flush(port_id);
 	}
 
-	if (ports[port_id].flow_list)
-		port_flow_flush(port_id);
-
 	if (rte_eth_dev_detach(port_id, name)) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v3 2/4] ethdev: free all common data when releasing port
  2018-10-17  1:54 ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Thomas Monjalon
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed Thomas Monjalon
@ 2018-10-17  1:54   ` Thomas Monjalon
  2018-10-17  7:13     ` Andrew Rybchenko
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 3/4] ethdev: remove release function for secondary process Thomas Monjalon
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  1:54 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

This is a clean-up of common ethdev data freeing.
All data freeing are moved to rte_eth_dev_release_port()
and done only in case of primary process.

It is probably fixing some memory leaks for PMDs which were
not freeing all data.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/net/af_packet/rte_eth_af_packet.c |  5 ++--
 drivers/net/ark/ark_ethdev.c              |  1 -
 drivers/net/avf/avf_ethdev.c              |  3 ---
 drivers/net/avp/avp_ethdev.c              |  5 ----
 drivers/net/axgbe/axgbe_ethdev.c          |  3 ---
 drivers/net/bnxt/bnxt_ethdev.c            |  4 ----
 drivers/net/bonding/rte_eth_bond_pmd.c    |  7 +-----
 drivers/net/cxgbe/cxgbe_main.c            | 16 ++-----------
 drivers/net/cxgbe/cxgbevf_main.c          |  9 +------
 drivers/net/dpaa/dpaa_ethdev.c            | 10 --------
 drivers/net/dpaa2/dpaa2_ethdev.c          | 10 --------
 drivers/net/e1000/em_ethdev.c             |  3 ---
 drivers/net/e1000/igb_ethdev.c            |  6 -----
 drivers/net/enetc/enetc_ethdev.c          |  4 +---
 drivers/net/failsafe/failsafe.c           |  6 +++--
 drivers/net/fm10k/fm10k_ethdev.c          |  8 -------
 drivers/net/i40e/i40e_ethdev.c            |  3 ---
 drivers/net/i40e/i40e_ethdev_vf.c         |  3 ---
 drivers/net/i40e/i40e_vf_representor.c    |  5 +++-
 drivers/net/ixgbe/ixgbe_ethdev.c          |  9 -------
 drivers/net/ixgbe/ixgbe_vf_representor.c  |  5 +++-
 drivers/net/kni/rte_eth_kni.c             |  5 ++--
 drivers/net/liquidio/lio_ethdev.c         |  3 ---
 drivers/net/mlx4/mlx4.c                   |  5 ++--
 drivers/net/mlx5/mlx5.c                   |  9 +++----
 drivers/net/mvneta/mvneta_ethdev.c        | 16 ++++---------
 drivers/net/mvpp2/mrvl_ethdev.c           | 16 ++++---------
 drivers/net/netvsc/hn_ethdev.c            | 15 ++----------
 drivers/net/null/rte_eth_null.c           |  4 ++--
 drivers/net/octeontx/octeontx_ethdev.c    | 29 +++++++++--------------
 drivers/net/pcap/rte_eth_pcap.c           |  8 +++----
 drivers/net/qede/qede_ethdev.c            |  5 ----
 drivers/net/ring/rte_eth_ring.c           |  6 ++---
 drivers/net/sfc/sfc_ethdev.c              |  3 ---
 drivers/net/softnic/rte_eth_softnic.c     |  7 +++---
 drivers/net/szedata2/rte_eth_szedata2.c   |  1 -
 drivers/net/tap/rte_eth_tap.c             |  6 ++++-
 drivers/net/vhost/rte_eth_vhost.c         |  9 +++----
 drivers/net/virtio/virtio_ethdev.c        |  3 ---
 drivers/net/virtio/virtio_user_ethdev.c   |  3 ---
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  3 ---
 lib/librte_ethdev/rte_ethdev.c            | 21 ++++++++--------
 lib/librte_ethdev/rte_ethdev_driver.h     | 11 ++++++++-
 lib/librte_ethdev/rte_ethdev_pci.h        | 10 --------
 44 files changed, 92 insertions(+), 231 deletions(-)

diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 376d76302..2efc17725 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -986,6 +986,9 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
@@ -996,8 +999,6 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	}
 	free(internals->if_name);
 
-	rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index 552ca01a6..70d62ec7f 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -506,7 +506,6 @@ eth_ark_dev_uninit(struct rte_eth_dev *dev)
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
-	rte_free(dev->data->mac_addrs);
 	return 0;
 }
 
diff --git a/drivers/net/avf/avf_ethdev.c b/drivers/net/avf/avf_ethdev.c
index e56d57c43..13eec1b45 100644
--- a/drivers/net/avf/avf_ethdev.c
+++ b/drivers/net/avf/avf_ethdev.c
@@ -1303,9 +1303,6 @@ avf_dev_uninit(struct rte_eth_dev *dev)
 	rte_free(vf->aq_resp);
 	vf->aq_resp = NULL;
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	if (vf->rss_lut) {
 		rte_free(vf->rss_lut);
 		vf->rss_lut = NULL;
diff --git a/drivers/net/avp/avp_ethdev.c b/drivers/net/avp/avp_ethdev.c
index 0f8ccb954..09388d05f 100644
--- a/drivers/net/avp/avp_ethdev.c
+++ b/drivers/net/avp/avp_ethdev.c
@@ -1036,11 +1036,6 @@ eth_avp_dev_uninit(struct rte_eth_dev *eth_dev)
 		return ret;
 	}
 
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index 4b84b50c0..e89c0ec2c 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -718,9 +718,6 @@ eth_axgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 		return 0;
 
 	pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
-	/*Free macaddres*/
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c11fe9c8c..801c6ffad 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -3501,10 +3501,6 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev)
 	bnxt_disable_int(bp);
 	bnxt_free_int(bp);
 	bnxt_free_mem(bp);
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
 	if (bp->grp_info != NULL) {
 		rte_free(bp->grp_info);
 		bp->grp_info = NULL;
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index b731132a5..082fc9d52 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3128,10 +3128,7 @@ bond_alloc(struct rte_vdev_device *dev, uint8_t mode)
 
 err:
 	rte_free(internals);
-	if (eth_dev != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		rte_eth_dev_release_port(eth_dev);
-	}
+	rte_eth_dev_release_port(eth_dev);
 	return -1;
 }
 
@@ -3292,8 +3289,6 @@ bond_remove(struct rte_vdev_device *dev)
 	rte_mempool_free(internals->mode6.mempool);
 	rte_bitmap_free(internals->vlan_filter_bmp);
 	rte_free(internals->vlan_filter_bmpmem);
-	rte_free(eth_dev->data->dev_private);
-	rte_free(eth_dev->data->mac_addrs);
 
 	rte_eth_dev_release_port(eth_dev);
 
diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
index a135df9c7..88dc851f8 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -1710,12 +1710,7 @@ void cxgbe_close(struct adapter *adapter)
 			if (pi->viid != 0)
 				t4_free_vi(adapter, adapter->mbox,
 					   adapter->pf, 0, pi->viid);
-			rte_free(pi->eth_dev->data->mac_addrs);
-			/* Skip first port since it'll be freed by DPDK stack */
-			if (i) {
-				rte_free(pi->eth_dev->data->dev_private);
-				rte_eth_dev_release_port(pi->eth_dev);
-			}
+			rte_eth_dev_release_port(pi->eth_dev);
 		}
 		adapter->flags &= ~FULL_INIT_DONE;
 	}
@@ -1918,14 +1913,7 @@ int cxgbe_probe(struct adapter *adapter)
 		if (pi->viid != 0)
 			t4_free_vi(adapter, adapter->mbox, adapter->pf,
 				   0, pi->viid);
-		/* Skip first port since it'll be de-allocated by DPDK */
-		if (i == 0)
-			continue;
-		if (pi->eth_dev) {
-			if (pi->eth_dev->data->dev_private)
-				rte_free(pi->eth_dev->data->dev_private);
-			rte_eth_dev_release_port(pi->eth_dev);
-		}
+		rte_eth_dev_release_port(pi->eth_dev);
 	}
 
 	if (adapter->flags & FW_OK)
diff --git a/drivers/net/cxgbe/cxgbevf_main.c b/drivers/net/cxgbe/cxgbevf_main.c
index 4214d0312..6223e1250 100644
--- a/drivers/net/cxgbe/cxgbevf_main.c
+++ b/drivers/net/cxgbe/cxgbevf_main.c
@@ -282,14 +282,7 @@ int cxgbevf_probe(struct adapter *adapter)
 		if (pi->viid != 0)
 			t4_free_vi(adapter, adapter->mbox, adapter->pf,
 				   0, pi->viid);
-		/* Skip first port since it'll be de-allocated by DPDK */
-		if (i == 0)
-			continue;
-		if (pi->eth_dev) {
-			if (pi->eth_dev->data->dev_private)
-				rte_free(pi->eth_dev->data->dev_private);
-			rte_eth_dev_release_port(pi->eth_dev);
-		}
+		rte_eth_dev_release_port(pi->eth_dev);
 	}
 	return -err;
 }
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 5c743c3c8..d0572b3d9 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1439,10 +1439,6 @@ dpaa_dev_uninit(struct rte_eth_dev *dev)
 	rte_free(dpaa_intf->tx_queues);
 	dpaa_intf->tx_queues = NULL;
 
-	/* free memory for storing MAC addresses */
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
@@ -1544,9 +1540,6 @@ rte_dpaa_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused,
 		return 0;
 	}
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 	return diag;
 }
@@ -1561,9 +1554,6 @@ rte_dpaa_remove(struct rte_dpaa_device *dpaa_dev)
 	eth_dev = dpaa_dev->eth_dev;
 	dpaa_dev_uninit(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 27ae4740e..af9db6beb 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -2062,12 +2062,6 @@ dpaa2_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	dpaa2_free_rx_tx_queues(eth_dev);
 
-	/* free memory for storing MAC addresses */
-	if (eth_dev->data->mac_addrs) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
-
 	/* Close the device at underlying layer*/
 	ret = dpni_close(dpni, CMD_PRI_LOW, priv->token);
 	if (ret) {
@@ -2130,8 +2124,6 @@ rte_dpaa2_probe(struct rte_dpaa2_driver *dpaa2_drv,
 		return 0;
 	}
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 	return diag;
 }
@@ -2144,8 +2136,6 @@ rte_dpaa2_remove(struct rte_dpaa2_device *dpaa2_dev)
 	eth_dev = dpaa2_dev->eth_dev;
 	dpaa2_dev_uninit(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 28c153512..8230824e7 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -329,9 +329,6 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(intr_handle);
 	rte_intr_callback_unregister(intr_handle,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e542ef572..d9d29d22f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -917,9 +917,6 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* Reset any pending lock */
 	igb_reset_swfw_lock(hw);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* uninitialize PF if max_vfs not zero */
 	igb_pf_host_uninit(eth_dev);
 
@@ -1073,9 +1070,6 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(&pci_dev->intr_handle);
 	rte_intr_callback_unregister(&pci_dev->intr_handle,
diff --git a/drivers/net/enetc/enetc_ethdev.c b/drivers/net/enetc/enetc_ethdev.c
index 3ee7bb446..023fe7517 100644
--- a/drivers/net/enetc/enetc_ethdev.c
+++ b/drivers/net/enetc/enetc_ethdev.c
@@ -108,11 +108,9 @@ enetc_dev_init(struct rte_eth_dev *eth_dev)
 }
 
 static int
-enetc_dev_uninit(struct rte_eth_dev *eth_dev)
+enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused)
 {
 	PMD_INIT_FUNC_TRACE();
-	rte_free(eth_dev->data->mac_addrs);
-
 	return 0;
 }
 
diff --git a/drivers/net/failsafe/failsafe.c b/drivers/net/failsafe/failsafe.c
index c3999f026..fed36da5f 100644
--- a/drivers/net/failsafe/failsafe.c
+++ b/drivers/net/failsafe/failsafe.c
@@ -280,7 +280,8 @@ fs_eth_dev_create(struct rte_vdev_device *vdev)
 free_subs:
 	fs_sub_device_free(dev);
 free_dev:
-	rte_free(PRIV(dev));
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(dev);
 	return -1;
 }
@@ -305,7 +306,8 @@ fs_rte_eth_free(const char *name)
 	if (ret)
 		ERROR("Error while destroying hotplug mutex");
 	rte_free(PRIV(dev)->mcast_addrs);
-	rte_free(PRIV(dev));
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(dev);
 	return ret;
 }
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 46983e5df..bb7b906a9 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3234,14 +3234,6 @@ eth_fm10k_dev_uninit(struct rte_eth_dev *dev)
 			fm10k_dev_interrupt_handler_vf, (void *)dev);
 	}
 
-	/* free mac memory */
-	if (dev->data->mac_addrs) {
-		rte_free(dev->data->mac_addrs);
-		dev->data->mac_addrs = NULL;
-	}
-
-	memset(hw, 0, sizeof(*hw));
-
 	return 0;
 }
 
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index f7a685c8c..8a5c3c8fb 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1728,9 +1728,6 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	/* uninitialize pf host driver */
 	i40e_pf_host_uninit(dev);
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(intr_handle);
 
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index baa6cc58f..ed2fc1310 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1483,9 +1483,6 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
 		return -1;
 	}
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/i40e/i40e_vf_representor.c b/drivers/net/i40e/i40e_vf_representor.c
index 24751d13c..43fe00cca 100644
--- a/drivers/net/i40e/i40e_vf_representor.c
+++ b/drivers/net/i40e/i40e_vf_representor.c
@@ -523,7 +523,10 @@ i40e_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params)
 }
 
 int
-i40e_vf_representor_uninit(struct rte_eth_dev *ethdev __rte_unused)
+i40e_vf_representor_uninit(struct rte_eth_dev *ethdev)
 {
+	/* mac_addrs must not be freed because part of i40e_pf_vf */
+	ethdev->data->mac_addrs = NULL;
+
 	return 0;
 }
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index c458bffc0..269595b73 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1337,12 +1337,6 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* uninitialize PF if max_vfs not zero */
 	ixgbe_pf_host_uninit(eth_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
-	rte_free(eth_dev->data->hash_mac_addrs);
-	eth_dev->data->hash_mac_addrs = NULL;
-
 	/* remove all the fdir filters & hash */
 	ixgbe_fdir_filter_uninit(eth_dev);
 
@@ -1722,9 +1716,6 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* Disable the interrupts for VF */
 	ixgbevf_intr_disable(eth_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	rte_intr_disable(intr_handle);
 	rte_intr_callback_unregister(intr_handle,
 				     ixgbevf_dev_interrupt_handler, eth_dev);
diff --git a/drivers/net/ixgbe/ixgbe_vf_representor.c b/drivers/net/ixgbe/ixgbe_vf_representor.c
index b0fbbc49f..eb9bbe5cb 100644
--- a/drivers/net/ixgbe/ixgbe_vf_representor.c
+++ b/drivers/net/ixgbe/ixgbe_vf_representor.c
@@ -225,7 +225,10 @@ ixgbe_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params)
 }
 
 int
-ixgbe_vf_representor_uninit(struct rte_eth_dev *ethdev __rte_unused)
+ixgbe_vf_representor_uninit(struct rte_eth_dev *ethdev)
 {
+	/* mac_addrs must not be freed because part of ixgbe_vf_info */
+	ethdev->data->mac_addrs = NULL;
+
 	return 0;
 }
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 72f3c16c1..f43ee7d2e 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -463,6 +463,9 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	if (eth_dev == NULL)
 		return -1;
 
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
@@ -471,8 +474,6 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	internals = eth_dev->data->dev_private;
 	rte_kni_release(internals->kni);
 
-	rte_free(internals);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	is_kni_initialized--;
diff --git a/drivers/net/liquidio/lio_ethdev.c b/drivers/net/liquidio/lio_ethdev.c
index 0f59e4475..d13ab06c0 100644
--- a/drivers/net/liquidio/lio_ethdev.c
+++ b/drivers/net/liquidio/lio_ethdev.c
@@ -2043,9 +2043,6 @@ lio_eth_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* lio_free_sc_buffer_pool */
 	lio_free_sc_buffer_pool(lio_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 3de7bc53e..81a719126 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -785,8 +785,9 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			claim_zero(mlx4_glue->dealloc_pd(pd));
 		if (ctx)
 			claim_zero(mlx4_glue->close_device(ctx));
-		if (eth_dev)
-			rte_eth_dev_release_port(eth_dev);
+		/* mac_addrs must not be freed because part of dev_private */
+		eth_dev->data->mac_addrs = NULL;
+		rte_eth_dev_release_port(eth_dev);
 		break;
 	}
 	/*
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 8cbfee1ba..aad82e4d1 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1226,8 +1226,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 	}
 	if (pd)
 		claim_zero(mlx5_glue->dealloc_pd(pd));
-	if (eth_dev)
-		rte_eth_dev_release_port(eth_dev);
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+	rte_eth_dev_release_port(eth_dev);
 	if (ctx)
 		claim_zero(mlx5_glue->close_device(ctx));
 	assert(err > 0);
@@ -1447,8 +1448,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 			if (!list[i].eth_dev)
 				continue;
 			mlx5_dev_close(list[i].eth_dev);
-			if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-				rte_free(list[i].eth_dev->data->dev_private);
+			/* mac_addrs must not be freed because in dev_private */
+			list[i].eth_dev->data->mac_addrs = NULL;
 			claim_zero(rte_eth_dev_release_port(list[i].eth_dev));
 		}
 		/* Restore original error. */
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index f7071bc2e..2d7666454 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -787,8 +787,9 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	priv = rte_zmalloc_socket(name, sizeof(*priv), 0, rte_socket_id());
 	if (!priv) {
 		ret = -ENOMEM;
-		goto out_free_dev;
+		goto out_free;
 	}
+	eth_dev->data->dev_private = priv;
 
 	eth_dev->data->mac_addrs =
 		rte_zmalloc("mac_addrs",
@@ -796,20 +797,19 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	if (!eth_dev->data->mac_addrs) {
 		MVNETA_LOG(ERR, "Failed to allocate space for eth addrs");
 		ret = -ENOMEM;
-		goto out_free_priv;
+		goto out_free;
 	}
 
 	memset(&req, 0, sizeof(req));
 	strcpy(req.ifr_name, name);
 	ret = ioctl(fd, SIOCGIFHWADDR, &req);
 	if (ret)
-		goto out_free_mac;
+		goto out_free;
 
 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
 
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
-	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
 	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
 	mvneta_set_tx_function(eth_dev);
@@ -817,11 +817,7 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 
 	rte_eth_dev_probing_finish(eth_dev);
 	return 0;
-out_free_mac:
-	rte_free(eth_dev->data->mac_addrs);
-out_free_priv:
-	rte_free(priv);
-out_free_dev:
+out_free:
 	rte_eth_dev_release_port(eth_dev);
 
 	return ret;
@@ -836,8 +832,6 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 static void
 mvneta_eth_dev_destroy(struct rte_eth_dev *eth_dev)
 {
-	rte_free(eth_dev->data->dev_private);
-	rte_free(eth_dev->data->mac_addrs);
 	rte_eth_dev_release_port(eth_dev);
 }
 
diff --git a/drivers/net/mvpp2/mrvl_ethdev.c b/drivers/net/mvpp2/mrvl_ethdev.c
index 0682c635a..ab4c14e51 100644
--- a/drivers/net/mvpp2/mrvl_ethdev.c
+++ b/drivers/net/mvpp2/mrvl_ethdev.c
@@ -2780,8 +2780,9 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	priv = mrvl_priv_create(name);
 	if (!priv) {
 		ret = -ENOMEM;
-		goto out_free_dev;
+		goto out_free;
 	}
+	eth_dev->data->dev_private = priv;
 
 	eth_dev->data->mac_addrs =
 		rte_zmalloc("mac_addrs",
@@ -2789,20 +2790,19 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	if (!eth_dev->data->mac_addrs) {
 		MRVL_LOG(ERR, "Failed to allocate space for eth addrs");
 		ret = -ENOMEM;
-		goto out_free_priv;
+		goto out_free;
 	}
 
 	memset(&req, 0, sizeof(req));
 	strcpy(req.ifr_name, name);
 	ret = ioctl(fd, SIOCGIFHWADDR, &req);
 	if (ret)
-		goto out_free_mac;
+		goto out_free;
 
 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
 
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
-	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
 	eth_dev->rx_pkt_burst = mrvl_rx_pkt_burst;
 	mrvl_set_tx_function(eth_dev);
@@ -2810,12 +2810,8 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 
 	rte_eth_dev_probing_finish(eth_dev);
 	return 0;
-out_free_mac:
-	rte_free(eth_dev->data->mac_addrs);
-out_free_dev:
+out_free:
 	rte_eth_dev_release_port(eth_dev);
-out_free_priv:
-	rte_free(priv);
 
 	return ret;
 }
@@ -2839,8 +2835,6 @@ mrvl_eth_dev_destroy(const char *name)
 	priv = eth_dev->data->dev_private;
 	pp2_bpool_deinit(priv->bpool);
 	used_bpools[priv->pp_id] &= ~(1 << priv->bpool_bit);
-	rte_free(priv);
-	rte_free(eth_dev->data->mac_addrs);
 	rte_eth_dev_release_port(eth_dev);
 }
 
diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c
index 8e728d639..aa38ee7a3 100644
--- a/drivers/net/netvsc/hn_ethdev.c
+++ b/drivers/net/netvsc/hn_ethdev.c
@@ -118,20 +118,11 @@ eth_dev_vmbus_allocate(struct rte_vmbus_device *dev, size_t private_data_size)
 static void
 eth_dev_vmbus_release(struct rte_eth_dev *eth_dev)
 {
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
 	/* free ether device */
 	rte_eth_dev_release_port(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
-	eth_dev->data->dev_private = NULL;
-
-	/*
-	 * Secondary process will check the name to attach.
-	 * Clear this field to avoid attaching a released ports.
-	 */
-	eth_dev->data->name[0] = '\0';
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 }
@@ -829,8 +820,6 @@ eth_hn_dev_uninit(struct rte_eth_dev *eth_dev)
 	rte_free(hv->primary);
 	rte_eth_dev_owner_delete(hv->owner.id);
 
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index 1e8237a41..b77283ae7 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -682,8 +682,8 @@ rte_pmd_null_remove(struct rte_vdev_device *dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
-	rte_free(eth_dev->data->dev_private);
-
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index 5431b44dc..746507912 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -1015,12 +1015,22 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 		return 0;
 	}
 
+	/* Reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(octtx_name);
+	if (eth_dev == NULL) {
+		octeontx_log_err("failed to allocate rte_eth_dev");
+		res = -ENOMEM;
+		goto err;
+	}
+	data = eth_dev->data;
+
 	nic = rte_zmalloc_socket(octtx_name, sizeof(*nic), 0, socket_id);
 	if (nic == NULL) {
 		octeontx_log_err("failed to allocate nic structure");
 		res = -ENOMEM;
 		goto err;
 	}
+	data->dev_private = nic;
 
 	nic->port_id = port;
 	nic->evdev = evdev;
@@ -1037,21 +1047,11 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 		goto err;
 	}
 
-	/* Reserve an ethdev entry */
-	eth_dev = rte_eth_dev_allocate(octtx_name);
-	if (eth_dev == NULL) {
-		octeontx_log_err("failed to allocate rte_eth_dev");
-		res = -ENOMEM;
-		goto err;
-	}
-
 	eth_dev->device = &dev->device;
 	eth_dev->intr_handle = NULL;
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->numa_node = dev->device.numa_node;
 
-	data = eth_dev->data;
-	data->dev_private = nic;
 	data->port_id = eth_dev->data->port_id;
 
 	nic->ev_queues = 1;
@@ -1103,12 +1103,7 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 	if (nic)
 		octeontx_port_close(nic);
 
-	if (eth_dev != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		rte_free(data);
-		rte_free(nic);
-		rte_eth_dev_release_port(eth_dev);
-	}
+	rte_eth_dev_release_port(eth_dev);
 
 	return res;
 }
@@ -1142,8 +1137,6 @@ octeontx_remove(struct rte_vdev_device *dev)
 		rte_event_dev_stop(nic->evdev);
 		PMD_INIT_LOG(INFO, "Closing octeontx device %s", octtx_name);
 
-		rte_free(eth_dev->data->mac_addrs);
-		rte_free(eth_dev->data->dev_private);
 		rte_eth_dev_release_port(eth_dev);
 		rte_event_dev_close(nic->evdev);
 	}
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index ede5ebb45..1790a8064 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -1232,11 +1232,9 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
 	internals = eth_dev->data->dev_private;
-	if (internals && internals->phy_mac)
-		rte_free(eth_dev->data->mac_addrs);
-
-	rte_free(eth_dev->data->dev_private);
-
+	if (internals != NULL && internals->phy_mac == 0)
+		/* not dynamically allocated, must not be freed */
+		eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 18d244a93..404859426 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2666,11 +2666,6 @@ static int qede_dev_common_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	if (eth_dev->data->mac_addrs)
-		rte_free(eth_dev->data->mac_addrs);
-
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/ring/rte_eth_ring.c b/drivers/net/ring/rte_eth_ring.c
index bfe2f1780..aeb48f5ec 100644
--- a/drivers/net/ring/rte_eth_ring.c
+++ b/drivers/net/ring/rte_eth_ring.c
@@ -666,10 +666,8 @@ rte_pmd_ring_remove(struct rte_vdev_device *dev)
 		}
 	}
 
-	rte_free(eth_dev->data->rx_queues);
-	rte_free(eth_dev->data->tx_queues);
-	rte_free(eth_dev->data->dev_private);
-
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 	return 0;
 }
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index b2e17f26e..3886daf7a 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -2035,9 +2035,6 @@ sfc_eth_dev_uninit(struct rte_eth_dev *dev)
 	sfc_detach(sa);
 	sfc_unprobe(sa);
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	sfc_kvargs_cleanup(sa);
 
 	sfc_adapter_unlock(sa);
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 0fd264e25..9a2418438 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -556,7 +556,6 @@ static int
 pmd_remove(struct rte_vdev_device *vdev)
 {
 	struct rte_eth_dev *dev = NULL;
-	struct pmd_internals *p;
 
 	if (!vdev)
 		return -EINVAL;
@@ -567,12 +566,12 @@ pmd_remove(struct rte_vdev_device *vdev)
 	dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
 	if (dev == NULL)
 		return -ENODEV;
-	p = dev->data->dev_private;
 
 	/* Free device data structures*/
-	rte_free(dev->data);
+	pmd_free(dev->data->dev_private);
+	dev->data->dev_private = NULL; /* already freed */
+	dev->data->mac_addrs = NULL; /* statically allocated */
 	rte_eth_dev_release_port(dev);
-	pmd_free(p);
 
 	return 0;
 }
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index 4e5e01cf1..88448eff6 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1544,7 +1544,6 @@ rte_szedata2_eth_dev_uninit(struct rte_eth_dev *dev)
 	PMD_INIT_FUNC_TRACE();
 
 	free(internals->sze_dev_path);
-	rte_free(dev->data->mac_addrs);
 
 	PMD_DRV_LOG(INFO, "%s device %s successfully uninitialized",
 			RTE_STR(RTE_SZEDATA2_DRIVER_NAME), dev->data->name);
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 84aaf2410..2327fbf8c 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1808,6 +1808,8 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, char *tap_name,
 error_exit:
 	if (pmd->ioctl_sock > 0)
 		close(pmd->ioctl_sock);
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(dev);
 
 error_exit_nodev:
@@ -2076,6 +2078,9 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	if (!eth_dev)
 		return -ENODEV;
 
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
@@ -2102,7 +2107,6 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	}
 
 	close(internals->ioctl_sock);
-	rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	if (internals->ka_fd != -1) {
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index a7604ff23..cf51c072d 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -1220,10 +1220,12 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internal));
 	if (eth_dev == NULL)
 		goto error;
+	data = eth_dev->data;
 
 	eth_addr = rte_zmalloc_socket(name, sizeof(*eth_addr), 0, numa_node);
 	if (eth_addr == NULL)
 		goto error;
+	data->mac_addrs = eth_addr;
 	*eth_addr = base_eth_addr;
 	eth_addr->addr_bytes[5] = eth_dev->data->port_id;
 
@@ -1253,13 +1255,11 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
 
-	data = eth_dev->data;
 	data->nb_rx_queues = queues;
 	data->nb_tx_queues = queues;
 	internal->max_queues = queues;
 	internal->vid = -1;
 	data->dev_link = pmd_link;
-	data->mac_addrs = eth_addr;
 	data->dev_flags = RTE_ETH_DEV_INTR_LSC;
 
 	eth_dev->dev_ops = &ops;
@@ -1291,10 +1291,7 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 		free(internal->dev_name);
 	}
 	rte_free(vring_state);
-	rte_free(eth_addr);
-	if (eth_dev)
-		rte_eth_dev_release_port(eth_dev);
-	rte_free(internal);
+	rte_eth_dev_release_port(eth_dev);
 	rte_free(list);
 
 	return -1;
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 730c41707..10a7e3fcc 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1706,9 +1706,6 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->tx_pkt_burst = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* reset interrupt callback  */
 	if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
 		rte_intr_callback_unregister(eth_dev->intr_handle,
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 525d16cab..420364b7a 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -422,7 +422,6 @@ virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev)
 	if (!dev) {
 		PMD_INIT_LOG(ERR, "malloc virtio_user_dev failed");
 		rte_eth_dev_release_port(eth_dev);
-		rte_free(hw);
 		return NULL;
 	}
 
@@ -449,7 +448,6 @@ virtio_user_eth_dev_free(struct rte_eth_dev *eth_dev)
 	struct virtio_hw *hw = data->dev_private;
 
 	rte_free(hw->virtio_user_dev);
-	rte_free(hw);
 	rte_eth_dev_release_port(eth_dev);
 }
 
@@ -662,7 +660,6 @@ virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 	dev = hw->virtio_user_dev;
 	virtio_user_dev_uninit(dev);
 
-	rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 78e5b7680..41bcd450a 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -368,9 +368,6 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->tx_pkt_burst = NULL;
 	eth_dev->tx_pkt_prepare = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 571f0e850..3bc05f4c3 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -388,7 +388,14 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 
 	eth_dev->state = RTE_ETH_DEV_UNUSED;
 
-	memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		rte_free(eth_dev->data->rx_queues);
+		rte_free(eth_dev->data->tx_queues);
+		rte_free(eth_dev->data->mac_addrs);
+		rte_free(eth_dev->data->hash_mac_addrs);
+		rte_free(eth_dev->data->dev_private);
+		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
+	}
 
 	rte_spinlock_unlock(&rte_eth_dev_shared_data->ownership_lock);
 
@@ -3529,7 +3536,7 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 			if (!ethdev->data->dev_private) {
 				RTE_LOG(ERR, EAL, "failed to allocate private data");
 				retval = -ENOMEM;
-				goto data_alloc_failed;
+				goto probe_failed;
 			}
 		}
 	} else {
@@ -3561,14 +3568,9 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 	rte_eth_dev_probing_finish(ethdev);
 
 	return retval;
-probe_failed:
-	/* free ports private data if primary process */
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(ethdev->data->dev_private);
 
-data_alloc_failed:
+probe_failed:
 	rte_eth_dev_release_port(ethdev);
-
 	return retval;
 }
 
@@ -3592,9 +3594,6 @@ rte_eth_dev_destroy(struct rte_eth_dev *ethdev,
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(ethdev);
 
-	rte_free(ethdev->data->dev_private);
-	ethdev->data->dev_private = NULL;
-
 	return rte_eth_dev_release_port(ethdev);
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index ca31b5777..a1398a80c 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -58,7 +58,16 @@ struct rte_eth_dev *rte_eth_dev_attach_secondary(const char *name);
 
 /**
  * @internal
- * Release the specified ethdev port.
+ * Notify RTE_ETH_EVENT_DESTROY and release the specified ethdev port.
+ *
+ * The following data fields will be freed:
+ *   - rx_queues
+ *   - tx_queues
+ *   - mac_addrs
+ *   - hash_mac_addrs
+ *   - dev_private
+ * If one of these fields should not be freed,
+ * it must be reset to NULL by the caller.
  *
  * @param eth_dev
  * Device to be detached.
diff --git a/lib/librte_ethdev/rte_ethdev_pci.h b/lib/librte_ethdev/rte_ethdev_pci.h
index 70d2d2503..8ff4f6b89 100644
--- a/lib/librte_ethdev/rte_ethdev_pci.h
+++ b/lib/librte_ethdev/rte_ethdev_pci.h
@@ -142,16 +142,6 @@ rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev)
 		return;
 	}
 
-	/* primary process */
-	rte_free(eth_dev->data->dev_private);
-	eth_dev->data->dev_private = NULL;
-
-	/*
-	 * Secondary process will check the name to attach.
-	 * Clear this field to avoid attaching a released ports.
-	 */
-	eth_dev->data->name[0] = '\0';
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v3 3/4] ethdev: remove release function for secondary process
  2018-10-17  1:54 ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Thomas Monjalon
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed Thomas Monjalon
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 2/4] ethdev: free all common data when releasing port Thomas Monjalon
@ 2018-10-17  1:54   ` Thomas Monjalon
  2018-10-17  7:25     ` Andrew Rybchenko
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 4/4] ethdev: complete closing of port Thomas Monjalon
  2018-10-17 10:24   ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Shreyansh Jain
  4 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  1:54 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

After previous changes, the function rte_eth_dev_release_port()
can be used for primary or secondary process as well.
The only difference with rte_eth_dev_release_port_secondary()
is the shared lock used in rte_eth_dev_release_port().

The function rte_eth_dev_release_port_secondary() was recently
added in 18.11 cycle.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/net/af_packet/rte_eth_af_packet.c |  2 +-
 drivers/net/bonding/rte_eth_bond_pmd.c    |  2 +-
 drivers/net/kni/rte_eth_kni.c             |  2 +-
 drivers/net/null/rte_eth_null.c           |  3 ---
 drivers/net/octeontx/octeontx_ethdev.c    |  2 +-
 drivers/net/pcap/rte_eth_pcap.c           |  3 ---
 drivers/net/tap/rte_eth_tap.c             |  2 +-
 drivers/net/vhost/rte_eth_vhost.c         |  2 +-
 lib/librte_ethdev/rte_ethdev.c            | 15 ---------------
 lib/librte_ethdev/rte_ethdev_driver.h     | 14 --------------
 lib/librte_ethdev/rte_ethdev_pci.h        |  7 -------
 lib/librte_ethdev/rte_ethdev_version.map  |  7 -------
 12 files changed, 6 insertions(+), 55 deletions(-)

diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 2efc17725..95a98c6b8 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -990,7 +990,7 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	eth_dev->data->mac_addrs = NULL;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	internals = eth_dev->data->dev_private;
 	for (q = 0; q < internals->nb_queues; q++) {
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 082fc9d52..860f3fdce 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3265,7 +3265,7 @@ bond_remove(struct rte_vdev_device *dev)
 		return -ENODEV;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	RTE_ASSERT(eth_dev->device == &dev->device);
 
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index f43ee7d2e..a1e9970df 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -467,7 +467,7 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	eth_dev->data->mac_addrs = NULL;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	eth_kni_dev_stop(eth_dev);
 
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index b77283ae7..c9bf15d75 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -679,9 +679,6 @@ rte_pmd_null_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
-
 	/* mac_addrs must not be freed alone because part of dev_private */
 	eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index 746507912..068148624 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -1129,7 +1129,7 @@ octeontx_remove(struct rte_vdev_device *dev)
 			return -ENODEV;
 
 		if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
-			rte_eth_dev_release_port_secondary(eth_dev);
+			rte_eth_dev_release_port(eth_dev);
 			continue;
 		}
 
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 1790a8064..bfb5d710d 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -1228,9 +1228,6 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
-
 	internals = eth_dev->data->dev_private;
 	if (internals != NULL && internals->phy_mac == 0)
 		/* not dynamically allocated, must not be freed */
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 2327fbf8c..53d37b3cb 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -2082,7 +2082,7 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	eth_dev->data->mac_addrs = NULL;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	internals = eth_dev->data->dev_private;
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index cf51c072d..0cd1a4642 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -1433,7 +1433,7 @@ rte_pmd_vhost_remove(struct rte_vdev_device *dev)
 		return -ENODEV;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	eth_dev_close(eth_dev);
 
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 3bc05f4c3..178800a5b 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -362,18 +362,6 @@ rte_eth_dev_attach_secondary(const char *name)
 	return eth_dev;
 }
 
-int
-rte_eth_dev_release_port_secondary(struct rte_eth_dev *eth_dev)
-{
-	if (eth_dev == NULL)
-		return -EINVAL;
-
-	_rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_DESTROY, NULL);
-	eth_dev->state = RTE_ETH_DEV_UNUSED;
-
-	return 0;
-}
-
 int
 rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 {
@@ -3591,9 +3579,6 @@ rte_eth_dev_destroy(struct rte_eth_dev *ethdev,
 			return ret;
 	}
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(ethdev);
-
 	return rte_eth_dev_release_port(ethdev);
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index a1398a80c..a539d3636 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -76,20 +76,6 @@ struct rte_eth_dev *rte_eth_dev_attach_secondary(const char *name);
  */
 int rte_eth_dev_release_port(struct rte_eth_dev *eth_dev);
 
-/**
- * @internal
- * Release the specified ethdev port in the local process.
- * Only set ethdev state to unused, but not reset shared data since
- * it assume other processes is still using it. typically it is
- * called by a secondary process.
- *
- * @param eth_dev
- * Device to be detached.
- * @return
- *   - 0 on success, negative on error
- */
-int rte_eth_dev_release_port_secondary(struct rte_eth_dev *eth_dev);
-
 /**
  * @internal
  * Release device queues and clear its configuration to force the user
diff --git a/lib/librte_ethdev/rte_ethdev_pci.h b/lib/librte_ethdev/rte_ethdev_pci.h
index 8ff4f6b89..23257e986 100644
--- a/lib/librte_ethdev/rte_ethdev_pci.h
+++ b/lib/librte_ethdev/rte_ethdev_pci.h
@@ -135,13 +135,6 @@ rte_eth_dev_pci_allocate(struct rte_pci_device *dev, size_t private_data_size)
 static inline void
 rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev)
 {
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
-		eth_dev->device = NULL;
-		eth_dev->intr_handle = NULL;
-		rte_eth_dev_release_port_secondary(eth_dev);
-		return;
-	}
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 3a4dd4790..dfa122c1a 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -220,13 +220,6 @@ DPDK_18.08 {
 
 } DPDK_18.05;
 
-DPDK_18.11 {
-	global:
-
-	rte_eth_dev_release_port_secondary;
-
-} DPDK_18.08;
-
 EXPERIMENTAL {
 	global:
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v3 4/4] ethdev: complete closing of port
  2018-10-17  1:54 ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Thomas Monjalon
                     ` (2 preceding siblings ...)
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 3/4] ethdev: remove release function for secondary process Thomas Monjalon
@ 2018-10-17  1:54   ` Thomas Monjalon
  2018-10-17  2:12     ` Thomas Monjalon
  2018-10-17 10:24   ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Shreyansh Jain
  4 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  1:54 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

After closing a port, it cannot be restarted.
So there is no reason to not free all associated resources.

The last step was done with rte_eth_dev_detach() which is deprecated.
Instead of blindly removing the associated rte_device, the driver should
check if no more port (ethdev, cryptodev, etc) is open for the device.

The last ethdev freeing which were done by rte_eth_dev_detach(),
are now done at the end of rte_eth_dev_close().

Some drivers does not allocate MAC addresses dynamically or separately.
In those cases, the pointer is set to NULL, in order to avoid wrongly
freeing them in rte_eth_dev_release_port().

If the driver is trying to free the port again, the function
rte_eth_dev_release_port() will abort with -ENODEV error.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/net/af_packet/rte_eth_af_packet.c | 4 +++-
 drivers/net/bnxt/bnxt_ethdev.c            | 4 ----
 drivers/net/failsafe/failsafe_ops.c       | 2 ++
 drivers/net/mlx4/mlx4.c                   | 2 ++
 drivers/net/mlx5/mlx5.c                   | 2 ++
 drivers/net/netvsc/hn_ethdev.c            | 5 ++++-
 drivers/net/pcap/rte_eth_pcap.c           | 5 +++++
 drivers/net/softnic/rte_eth_softnic.c     | 3 ++-
 drivers/net/tap/rte_eth_tap.c             | 3 +++
 drivers/net/vhost/rte_eth_vhost.c         | 4 ----
 lib/librte_ethdev/rte_ethdev.c            | 9 +++------
 lib/librte_ethdev/rte_ethdev.h            | 3 +--
 12 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 95a98c6b8..2678335f6 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -362,8 +362,10 @@ eth_stats_reset(struct rte_eth_dev *dev)
 }
 
 static void
-eth_dev_close(struct rte_eth_dev *dev __rte_unused)
+eth_dev_close(struct rte_eth_dev *dev)
 {
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 }
 
 static void
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 801c6ffad..141bd6376 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -712,10 +712,6 @@ static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (bp->dev_stopped == 0)
 		bnxt_dev_stop_op(eth_dev);
 
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
 	if (bp->grp_info != NULL) {
 		rte_free(bp->grp_info);
 		bp->grp_info = NULL;
diff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c
index 7f8bcd4c6..f10433b30 100644
--- a/drivers/net/failsafe/failsafe_ops.c
+++ b/drivers/net/failsafe/failsafe_ops.c
@@ -331,6 +331,8 @@ fs_dev_close(struct rte_eth_dev *dev)
 		sdev->state = DEV_ACTIVE - 1;
 	}
 	fs_dev_free_queues(dev);
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	fs_unlock(dev, 0);
 }
 
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 81a719126..084a456e3 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -218,6 +218,8 @@ mlx4_dev_close(struct rte_eth_dev *dev)
 		assert(priv->ctx == NULL);
 	mlx4_intr_uninstall(priv);
 	memset(priv, 0, sizeof(*priv));
+	/* mac_addrs must not be freed because part of dev_private */
+	dev->data->mac_addrs = NULL;
 }
 
 static const struct eth_dev_ops mlx4_dev_ops = {
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index aad82e4d1..9870da51d 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -337,6 +337,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 	}
 	memset(priv, 0, sizeof(*priv));
 	priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 }
 
 const struct eth_dev_ops mlx5_dev_ops = {
diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c
index aa38ee7a3..5a7463628 100644
--- a/drivers/net/netvsc/hn_ethdev.c
+++ b/drivers/net/netvsc/hn_ethdev.c
@@ -630,11 +630,14 @@ hn_dev_stop(struct rte_eth_dev *dev)
 }
 
 static void
-hn_dev_close(struct rte_eth_dev *dev __rte_unused)
+hn_dev_close(struct rte_eth_dev *dev)
 {
 	PMD_INIT_LOG(DEBUG, "close");
 
 	hn_vf_close(dev);
+
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 }
 
 static const struct eth_dev_ops hn_eth_dev_ops = {
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index bfb5d710d..261b09c4f 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -623,6 +623,11 @@ eth_stats_reset(struct rte_eth_dev *dev)
 static void
 eth_dev_close(struct rte_eth_dev *dev __rte_unused)
 {
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	if (internals != NULL && internals->phy_mac == 0)
+		/* not dynamically allocated, must not be freed */
+		dev->data->mac_addrs = NULL;
 }
 
 static void
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 9a2418438..083519b38 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -194,8 +194,9 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 }
 
 static void
-pmd_dev_close(struct rte_eth_dev *dev __rte_unused)
+pmd_dev_close(struct rte_eth_dev *dev)
 {
+	dev->data->mac_addrs = NULL; /* statically allocated */
 	return;
 }
 
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 53d37b3cb..32f2f888d 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1000,6 +1000,9 @@ tap_dev_close(struct rte_eth_dev *dev)
 	 * Since TUN device has no more opened file descriptors
 	 * it will be removed from kernel
 	 */
+
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 }
 
 static void
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 0cd1a4642..d3e78503b 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -998,12 +998,8 @@ eth_dev_close(struct rte_eth_dev *dev)
 		for (i = 0; i < dev->data->nb_tx_queues; i++)
 			rte_free(dev->data->tx_queues[i]);
 
-	rte_free(dev->data->mac_addrs);
 	free(internal->dev_name);
 	free(internal->iface_name);
-	rte_free(internal);
-
-	dev->data->dev_private = NULL;
 }
 
 static int
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 178800a5b..987ba5ab1 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -367,6 +367,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 {
 	if (eth_dev == NULL)
 		return -EINVAL;
+	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
+		return -ENODEV;
 
 	rte_eth_dev_shared_data_prepare();
 
@@ -1384,12 +1386,7 @@ rte_eth_dev_close(uint16_t port_id)
 	dev->data->dev_started = 0;
 	(*dev->dev_ops->dev_close)(dev);
 
-	dev->data->nb_rx_queues = 0;
-	rte_free(dev->data->rx_queues);
-	dev->data->rx_queues = NULL;
-	dev->data->nb_tx_queues = 0;
-	rte_free(dev->data->tx_queues);
-	dev->data->tx_queues = NULL;
+	rte_eth_dev_release_port(dev);
 }
 
 int
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index fb40c89e0..dcdeb184b 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1802,8 +1802,7 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
 
 /**
  * Close a stopped Ethernet device. The device cannot be restarted!
- * The function frees all resources except for needed by the
- * closed state. To free these resources, call rte_eth_dev_detach().
+ * The function frees all port resources.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed Thomas Monjalon
@ 2018-10-17  2:06     ` Thomas Monjalon
  2018-10-17  6:26     ` Andrew Rybchenko
  1 sibling, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  2:06 UTC (permalink / raw)
  To: bernard.iremonger; +Cc: dev, ferruh.yigit, arybchenko, ophirmu

+Cc Bernard

Note that the function port_is_closed is replaced because
a closed port is always seen as invalid after this series:
the state is set to RTE_ETH_DEV_UNUSED by rte_eth_dev_release_port().
I may split this patch and add a release note to make it clear.


17/10/2018 03:54, Thomas Monjalon:
> The testpmd application aim is for testing;
> so order of operations should not be enforced.
> 
> There was a test to forbid detaching before closing a port.
> However, it may interesting to test what happens in such case.
> It is possible for a PMD to automatically close the port when detaching.
> 
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
>  app/test-pmd/testpmd.c | 22 ++++------------------
>  1 file changed, 4 insertions(+), 18 deletions(-)
> 
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> index 5dbbf783f..f5dee1d71 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -1938,18 +1938,6 @@ port_is_started(portid_t port_id)
>  	return 1;
>  }
>  
> -static int
> -port_is_closed(portid_t port_id)
> -{
> -	if (port_id_is_invalid(port_id, ENABLED_WARN))
> -		return 0;
> -
> -	if (ports[port_id].port_status != RTE_PORT_CLOSED)
> -		return 0;
> -
> -	return 1;
> -}
> -
>  int
>  start_port(portid_t pid)
>  {
> @@ -2319,14 +2307,12 @@ detach_port(portid_t port_id)
>  
>  	printf("Detaching a port...\n");
>  
> -	if (!port_is_closed(port_id)) {
> -		printf("Please close port first\n");
> -		return;
> +	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
> +		printf("Port not closed\n");
> +		if (ports[port_id].flow_list)
> +			port_flow_flush(port_id);
>  	}
>  
> -	if (ports[port_id].flow_list)
> -		port_flow_flush(port_id);
> -
>  	if (rte_eth_dev_detach(port_id, name)) {
>  		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
>  		return;
> 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 4/4] ethdev: complete closing of port
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 4/4] ethdev: complete closing of port Thomas Monjalon
@ 2018-10-17  2:12     ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  2:12 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko; +Cc: dev, ophirmu

17/10/2018 03:54, Thomas Monjalon:
> After closing a port, it cannot be restarted.
> So there is no reason to not free all associated resources.
> 
> The last step was done with rte_eth_dev_detach() which is deprecated.
> Instead of blindly removing the associated rte_device, the driver should
> check if no more port (ethdev, cryptodev, etc) is open for the device.
> 
> The last ethdev freeing which were done by rte_eth_dev_detach(),
> are now done at the end of rte_eth_dev_close().
[...]
>  /**
>   * Close a stopped Ethernet device. The device cannot be restarted!
> - * The function frees all resources except for needed by the
> - * closed state. To free these resources, call rte_eth_dev_detach().
> + * The function frees all port resources.
[...]
> @@ -1384,12 +1386,7 @@ rte_eth_dev_close(uint16_t port_id)
> +	rte_eth_dev_release_port(dev);

After more thoughts, I think I should add a release note to explain that
a closed port has its data freed and its state to RTE_ETH_DEV_UNUSED.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed Thomas Monjalon
  2018-10-17  2:06     ` Thomas Monjalon
@ 2018-10-17  6:26     ` Andrew Rybchenko
  2018-10-17  8:20       ` Thomas Monjalon
  1 sibling, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-17  6:26 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit; +Cc: dev, ophirmu

On 10/17/18 4:54 AM, Thomas Monjalon wrote:
> The testpmd application aim is for testing;
> so order of operations should not be enforced.
>
> There was a test to forbid detaching before closing a port.
> However, it may interesting to test what happens in such case.
> It is possible for a PMD to automatically close the port when detaching.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

I'm afraid it could be a problem which the patch, since port
close ensures that the port is not used for traffic forwarding.
Right now the check is gone and we can detach port which
is used for traffic forwarding on separate data cores.
So, almost guaranteed crash.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/4] ethdev: free all common data when releasing port
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 2/4] ethdev: free all common data when releasing port Thomas Monjalon
@ 2018-10-17  7:13     ` Andrew Rybchenko
  2018-10-17  8:22       ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-17  7:13 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit; +Cc: dev, ophirmu

On 10/17/18 4:54 AM, Thomas Monjalon wrote:
> This is a clean-up of common ethdev data freeing.
> All data freeing are moved to rte_eth_dev_release_port()
> and done only in case of primary process.
>
> It is probably fixing some memory leaks for PMDs which were
> not freeing all data.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

[...]

> diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
> index ca31b5777..a1398a80c 100644
> --- a/lib/librte_ethdev/rte_ethdev_driver.h
> +++ b/lib/librte_ethdev/rte_ethdev_driver.h
> @@ -58,7 +58,16 @@ struct rte_eth_dev *rte_eth_dev_attach_secondary(const char *name);
>   
>   /**
>    * @internal
> - * Release the specified ethdev port.
> + * Notify RTE_ETH_EVENT_DESTROY and release the specified ethdev port.
> + *
> + * The following data fields will be freed:
> + *   - rx_queues
> + *   - tx_queues

I think rx_queues and tx_queues from should not be mentioned here.
They are managed by ethdev and there is no options here.

> + *   - mac_addrs
> + *   - hash_mac_addrs
> + *   - dev_private
> + * If one of these fields should not be freed,
> + * it must be reset to NULL by the caller.

I'm afraid nobody will find it here. Let's add
@see rte_eth_dev_release_port()
to these members description in rte_ethdev_core.h
struct rte_eth_dev_data.

Also I think "by the caller" is misleading here.
Let's highlight that it is PMD responsibility, i.e.
"by the PMD" may be with
"typically in dev_close method implementation".

Andrew.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/4] ethdev: remove release function for secondary process
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 3/4] ethdev: remove release function for secondary process Thomas Monjalon
@ 2018-10-17  7:25     ` Andrew Rybchenko
  2018-10-17  9:27       ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-17  7:25 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit; +Cc: dev, ophirmu

On 10/17/18 4:54 AM, Thomas Monjalon wrote:
> After previous changes, the function rte_eth_dev_release_port()
> can be used for primary or secondary process as well.
> The only difference with rte_eth_dev_release_port_secondary()
> is the shared lock used in rte_eth_dev_release_port().
>
> The function rte_eth_dev_release_port_secondary() was recently
> added in 18.11 cycle.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

I really like it. Few notes below.

> diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
> index b77283ae7..c9bf15d75 100644
> --- a/drivers/net/null/rte_eth_null.c
> +++ b/drivers/net/null/rte_eth_null.c
> @@ -679,9 +679,6 @@ rte_pmd_null_remove(struct rte_vdev_device *dev)
>   	if (eth_dev == NULL)
>   		return -1;
>   
> -	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
> -		return rte_eth_dev_release_port_secondary(eth_dev);
> -
>   	/* mac_addrs must not be freed alone because part of dev_private */
>   	eth_dev->data->mac_addrs = NULL;

I think it should be done in primary process only.

>   	rte_eth_dev_release_port(eth_dev);
> diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
> index 1790a8064..bfb5d710d 100644
> --- a/drivers/net/pcap/rte_eth_pcap.c
> +++ b/drivers/net/pcap/rte_eth_pcap.c
> @@ -1228,9 +1228,6 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
>   	if (eth_dev == NULL)
>   		return -1;
>   
> -	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
> -		return rte_eth_dev_release_port_secondary(eth_dev);
> -
>   	internals = eth_dev->data->dev_private;
>   	if (internals != NULL && internals->phy_mac == 0)
>   		/* not dynamically allocated, must not be freed */

Like above I think that assignment (which follows) should be done
in the primary process only.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed
  2018-10-17  6:26     ` Andrew Rybchenko
@ 2018-10-17  8:20       ` Thomas Monjalon
  2018-10-17 10:30         ` Iremonger, Bernard
  0 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  8:20 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu

17/10/2018 08:26, Andrew Rybchenko:
> On 10/17/18 4:54 AM, Thomas Monjalon wrote:
> > The testpmd application aim is for testing;
> > so order of operations should not be enforced.
> >
> > There was a test to forbid detaching before closing a port.
> > However, it may interesting to test what happens in such case.
> > It is possible for a PMD to automatically close the port when detaching.
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> 
> I'm afraid it could be a problem which the patch, since port
> close ensures that the port is not used for traffic forwarding.
> Right now the check is gone and we can detach port which
> is used for traffic forwarding on separate data cores.
> So, almost guaranteed crash.

Yes I can duplicate this check in detach_port().

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/4] ethdev: free all common data when releasing port
  2018-10-17  7:13     ` Andrew Rybchenko
@ 2018-10-17  8:22       ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  8:22 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu

17/10/2018 09:13, Andrew Rybchenko:
> On 10/17/18 4:54 AM, Thomas Monjalon wrote:
> > This is a clean-up of common ethdev data freeing.
> > All data freeing are moved to rte_eth_dev_release_port()
> > and done only in case of primary process.
> >
> > It is probably fixing some memory leaks for PMDs which were
> > not freeing all data.
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> 
> [...]
> 
> > diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
> > index ca31b5777..a1398a80c 100644
> > --- a/lib/librte_ethdev/rte_ethdev_driver.h
> > +++ b/lib/librte_ethdev/rte_ethdev_driver.h
> > @@ -58,7 +58,16 @@ struct rte_eth_dev *rte_eth_dev_attach_secondary(const char *name);
> >   
> >   /**
> >    * @internal
> > - * Release the specified ethdev port.
> > + * Notify RTE_ETH_EVENT_DESTROY and release the specified ethdev port.
> > + *
> > + * The following data fields will be freed:
> > + *   - rx_queues
> > + *   - tx_queues
> 
> I think rx_queues and tx_queues from should not be mentioned here.
> They are managed by ethdev and there is no options here.
> 
> > + *   - mac_addrs
> > + *   - hash_mac_addrs
> > + *   - dev_private
> > + * If one of these fields should not be freed,
> > + * it must be reset to NULL by the caller.
> 
> I'm afraid nobody will find it here. Let's add
> @see rte_eth_dev_release_port()
> to these members description in rte_ethdev_core.h
> struct rte_eth_dev_data.
> 
> Also I think "by the caller" is misleading here.
> Let's highlight that it is PMD responsibility, i.e.
> "by the PMD" may be with
> "typically in dev_close method implementation".

OK, thanks for the feedback.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/4] ethdev: remove release function for secondary process
  2018-10-17  7:25     ` Andrew Rybchenko
@ 2018-10-17  9:27       ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17  9:27 UTC (permalink / raw)
  To: Andrew Rybchenko; +Cc: ferruh.yigit, dev, ophirmu

17/10/2018 09:25, Andrew Rybchenko:
> On 10/17/18 4:54 AM, Thomas Monjalon wrote:
> > After previous changes, the function rte_eth_dev_release_port()
> > can be used for primary or secondary process as well.
> > The only difference with rte_eth_dev_release_port_secondary()
> > is the shared lock used in rte_eth_dev_release_port().
> >
> > The function rte_eth_dev_release_port_secondary() was recently
> > added in 18.11 cycle.
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> 
> I really like it. Few notes below.
> 
> > diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
> > index b77283ae7..c9bf15d75 100644
> > --- a/drivers/net/null/rte_eth_null.c
> > +++ b/drivers/net/null/rte_eth_null.c
> > @@ -679,9 +679,6 @@ rte_pmd_null_remove(struct rte_vdev_device *dev)
> >   	if (eth_dev == NULL)
> >   		return -1;
> >   
> > -	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
> > -		return rte_eth_dev_release_port_secondary(eth_dev);
> > -
> >   	/* mac_addrs must not be freed alone because part of dev_private */
> >   	eth_dev->data->mac_addrs = NULL;
> 
> I think it should be done in primary process only.
> 
> >   	rte_eth_dev_release_port(eth_dev);
> > diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
> > index 1790a8064..bfb5d710d 100644
> > --- a/drivers/net/pcap/rte_eth_pcap.c
> > +++ b/drivers/net/pcap/rte_eth_pcap.c
> > @@ -1228,9 +1228,6 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
> >   	if (eth_dev == NULL)
> >   		return -1;
> >   
> > -	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
> > -		return rte_eth_dev_release_port_secondary(eth_dev);
> > -
> >   	internals = eth_dev->data->dev_private;
> >   	if (internals != NULL && internals->phy_mac == 0)
> >   		/* not dynamically allocated, must not be freed */
> 
> Like above I think that assignment (which follows) should be done
> in the primary process only.

I am not sure it has a real impact, because all processes are removing
the device which should be already stopped.
But OK, I will avoid changing shared data in secondary process.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] ethdev port freeing
  2018-10-17  1:54 ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Thomas Monjalon
                     ` (3 preceding siblings ...)
  2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 4/4] ethdev: complete closing of port Thomas Monjalon
@ 2018-10-17 10:24   ` Shreyansh Jain
  2018-10-17 11:31     ` Thomas Monjalon
  4 siblings, 1 reply; 78+ messages in thread
From: Shreyansh Jain @ 2018-10-17 10:24 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: ferruh.yigit, arybchenko, dev, ophirmu

On 10/17/2018 7:24 AM, Thomas Monjalon wrote:
> 

[...]

> 
> Note: this patchset depends on multi-process hotplug series by Qi Zhang,
> which is accepted but waiting for an unrelated DPAA compilation issue
> to be fixed, before landing on master tree.
> 

Can you please point me to which DPAA compilation issue is being 
referred here?

Is that [1]? (which is DPAA2 and patch already sent)

[1] https://mails.dpdk.org/archives/test-report/2018-October/066840.html

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed
  2018-10-17  8:20       ` Thomas Monjalon
@ 2018-10-17 10:30         ` Iremonger, Bernard
  2018-10-17 11:33           ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Iremonger, Bernard @ 2018-10-17 10:30 UTC (permalink / raw)
  To: Thomas Monjalon, Andrew Rybchenko; +Cc: Yigit, Ferruh, dev, ophirmu

Hi Thomas,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> Sent: Wednesday, October 17, 2018 9:21 AM
> To: Andrew Rybchenko <arybchenko@solarflare.com>
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; dev@dpdk.org;
> ophirmu@mellanox.com
> Subject: Re: [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not
> closed
> 
> 17/10/2018 08:26, Andrew Rybchenko:
> > On 10/17/18 4:54 AM, Thomas Monjalon wrote:
> > > The testpmd application aim is for testing; so order of operations
> > > should not be enforced.
> > >
> > > There was a test to forbid detaching before closing a port.
> > > However, it may interesting to test what happens in such case.
> > > It is possible for a PMD to automatically close the port when detaching.
> > >
> > > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> >
> > I'm afraid it could be a problem which the patch, since port close
> > ensures that the port is not used for traffic forwarding.
> > Right now the check is gone and we can detach port which is used for
> > traffic forwarding on separate data cores.
> > So, almost guaranteed crash.
> 
> Yes I can duplicate this check in detach_port().

I agree with Andrew that this will cause a crash.

I don't understand why the sequence is changing here.
The close(), detach()  sequence has been in place since the port hot plug work some years ago, user applications may already be using this sequence.

Regards,

Bernard.

 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] ethdev port freeing
  2018-10-17 10:24   ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Shreyansh Jain
@ 2018-10-17 11:31     ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17 11:31 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: ferruh.yigit, arybchenko, dev, ophirmu

17/10/2018 12:24, Shreyansh Jain:
> On 10/17/2018 7:24 AM, Thomas Monjalon wrote:
> > Note: this patchset depends on multi-process hotplug series by Qi Zhang,
> > which is accepted but waiting for an unrelated DPAA compilation issue
> > to be fixed, before landing on master tree.
> > 
> 
> Can you please point me to which DPAA compilation issue is being 
> referred here?
> 
> Is that [1]? (which is DPAA2 and patch already sent)
> 
> [1] https://mails.dpdk.org/archives/test-report/2018-October/066840.html

Yes, you fixed it.

So multi-process hotplug series is now on master branch.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed
  2018-10-17 10:30         ` Iremonger, Bernard
@ 2018-10-17 11:33           ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-17 11:33 UTC (permalink / raw)
  To: Iremonger, Bernard; +Cc: Andrew Rybchenko, Yigit, Ferruh, dev, ophirmu

17/10/2018 12:30, Iremonger, Bernard:
> Hi Thomas,
> 
> From: Thomas Monjalon
> > 17/10/2018 08:26, Andrew Rybchenko:
> > > On 10/17/18 4:54 AM, Thomas Monjalon wrote:
> > > > The testpmd application aim is for testing; so order of operations
> > > > should not be enforced.
> > > >
> > > > There was a test to forbid detaching before closing a port.
> > > > However, it may interesting to test what happens in such case.
> > > > It is possible for a PMD to automatically close the port when detaching.
> > > >
> > > > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > >
> > > I'm afraid it could be a problem which the patch, since port close
> > > ensures that the port is not used for traffic forwarding.
> > > Right now the check is gone and we can detach port which is used for
> > > traffic forwarding on separate data cores.
> > > So, almost guaranteed crash.
> > 
> > Yes I can duplicate this check in detach_port().
> 
> I agree with Andrew that this will cause a crash.

As I answered, I will add a check that port is stopped.

> I don't understand why the sequence is changing here.
> The close(), detach()  sequence has been in place since the port hot plug work some years ago, user applications may already be using this sequence.

I explained the reason in the commit log:
Adding too much checks is wrong for a test application.
We must be free to call detach without close.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v5 0/6] ethdev port freeing
  2018-09-07 23:39 [dpdk-dev] [RFC] ethdev: complete closing to free all resources Thomas Monjalon
                   ` (4 preceding siblings ...)
  2018-10-17  1:54 ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Thomas Monjalon
@ 2018-10-18  1:23 ` Thomas Monjalon
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once Thomas Monjalon
                     ` (5 more replies)
  2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
  6 siblings, 6 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:23 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

The function rte_eth_dev_detach() is freeing a port and its underlying
rte_device object. The issue is that we may have several ports
associated to the same rte_device.

The right replacement is to free the port, and free the rte_device
if no more ports.
At ethdev level, the public function for port freeing is rte_eth_dev_close().
The only miss is rte_eth_dev_release_port() to free all port resources.

This patchset does a cleanup by moving as much ethdev data freeing
as possible in an unique function rte_eth_dev_release_port(),
and call this function in rte_eth_dev_close().


Changes in v5:
  - fix testpmd for detaching multi-ports device
  - fix testpmd for detaching only stopped ports
  - add a release note about closed port freeing and state
  - fix some doxygen comments in rte_eth_dev_data
  - improve doxygen of rte_eth_dev_release_port()
  - fix data freeing in some drivers

Changes in v4:
  - do not free data fields which are not dynamically allocated blocks
  - remove rte_eth_dev_release_port_secondary()
  - remove testpmd check to detach without closing

Changes in v3:
  - free queues, MAC addresses and private structure
    in rte_eth_dev_release_port.


Thomas Monjalon (5):
  app/testpmd: allow detaching a port not closed
  ethdev: fix doxygen comments of shared data fields
  ethdev: free all common data when releasing port
  ethdev: remove release function for secondary process
  ethdev: complete closing of port

Wisam Jaddo (1):
  app/testpmd: fix ports list after removing several at once

 app/test-pmd/testpmd.c                    | 64 +++++++++++++----------
 doc/guides/rel_notes/release_18_11.rst    |  4 ++
 drivers/net/af_packet/rte_eth_af_packet.c | 11 ++--
 drivers/net/ark/ark_ethdev.c              |  1 -
 drivers/net/avf/avf_ethdev.c              |  3 --
 drivers/net/avp/avp_ethdev.c              |  5 --
 drivers/net/axgbe/axgbe_ethdev.c          |  3 --
 drivers/net/bnxt/bnxt_ethdev.c            |  8 ---
 drivers/net/bonding/rte_eth_bond_pmd.c    | 11 ++--
 drivers/net/cxgbe/cxgbe_main.c            | 16 +-----
 drivers/net/cxgbe/cxgbevf_main.c          |  9 +---
 drivers/net/dpaa/dpaa_ethdev.c            | 10 ----
 drivers/net/dpaa2/dpaa2_ethdev.c          | 10 ----
 drivers/net/e1000/em_ethdev.c             |  3 --
 drivers/net/e1000/igb_ethdev.c            |  6 ---
 drivers/net/enetc/enetc_ethdev.c          |  4 +-
 drivers/net/failsafe/failsafe.c           |  6 ++-
 drivers/net/failsafe/failsafe_ops.c       |  2 +
 drivers/net/fm10k/fm10k_ethdev.c          |  8 ---
 drivers/net/i40e/i40e_ethdev.c            |  3 --
 drivers/net/i40e/i40e_ethdev_vf.c         |  3 --
 drivers/net/i40e/i40e_vf_representor.c    |  5 +-
 drivers/net/ixgbe/ixgbe_ethdev.c          |  9 ----
 drivers/net/ixgbe/ixgbe_vf_representor.c  |  5 +-
 drivers/net/kni/rte_eth_kni.c             |  7 +--
 drivers/net/liquidio/lio_ethdev.c         |  3 --
 drivers/net/mlx4/mlx4.c                   |  9 +++-
 drivers/net/mlx5/mlx5.c                   | 13 +++--
 drivers/net/mvneta/mvneta_ethdev.c        | 16 ++----
 drivers/net/mvpp2/mrvl_ethdev.c           | 16 ++----
 drivers/net/netvsc/hn_ethdev.c            | 20 +++----
 drivers/net/null/rte_eth_null.c           |  7 ++-
 drivers/net/octeontx/octeontx_ethdev.c    | 31 +++++------
 drivers/net/pcap/rte_eth_pcap.c           | 19 ++++---
 drivers/net/qede/qede_ethdev.c            |  5 --
 drivers/net/ring/rte_eth_ring.c           |  6 +--
 drivers/net/sfc/sfc_ethdev.c              |  3 --
 drivers/net/softnic/rte_eth_softnic.c     | 10 ++--
 drivers/net/szedata2/rte_eth_szedata2.c   |  1 -
 drivers/net/tap/rte_eth_tap.c             | 11 +++-
 drivers/net/vhost/rte_eth_vhost.c         | 15 ++----
 drivers/net/virtio/virtio_ethdev.c        |  3 --
 drivers/net/virtio/virtio_user_ethdev.c   |  3 --
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  3 --
 lib/librte_ethdev/rte_ethdev.c            | 45 +++++-----------
 lib/librte_ethdev/rte_ethdev.h            |  3 +-
 lib/librte_ethdev/rte_ethdev_core.h       | 38 ++++++++------
 lib/librte_ethdev/rte_ethdev_driver.h     | 23 +++-----
 lib/librte_ethdev/rte_ethdev_pci.h        | 17 ------
 lib/librte_ethdev/rte_ethdev_version.map  |  7 ---
 50 files changed, 196 insertions(+), 347 deletions(-)

-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once
  2018-10-18  1:23 ` [dpdk-dev] [PATCH v5 0/6] " Thomas Monjalon
@ 2018-10-18  1:23   ` Thomas Monjalon
  2018-10-18 10:40     ` Iremonger, Bernard
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 2/6] app/testpmd: allow detaching a port not closed Thomas Monjalon
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:23 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy, Wisam Jaddo

From: Wisam Jaddo <wisamm@mellanox.com>

When detaching a port, the full rte_device is removed.
If the rte_device was hosting several ports,
the testpmd list of ports must be updated for multiple removals.

Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
---
 app/test-pmd/testpmd.c | 36 +++++++++++++++++++++++++-----------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 5dbbf783f..c4109417a 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2186,6 +2186,30 @@ stop_port(portid_t pid)
 	printf("Done\n");
 }
 
+static void
+remove_unused_fwd_ports(void)
+{
+	int i;
+	int last_port_idx = nb_ports - 1;
+
+	for (i = 0; i < last_port_idx + 1; i++) { /* iterate in ports_ids */
+		if (rte_eth_devices[ports_ids[i]].state == RTE_ETH_DEV_UNUSED) {
+			/* skip unused ports at the end */
+			while (rte_eth_devices[ports_ids[last_port_idx]].state
+					== RTE_ETH_DEV_UNUSED && i <= last_port_idx)
+				last_port_idx--;
+			if (last_port_idx < i)
+				break;
+			/* overwrite unused port with last valid port */
+			ports_ids[i] = ports_ids[last_port_idx];
+			/* decrease ports count */
+			last_port_idx--;
+		}
+	}
+	nb_ports = rte_eth_dev_count_avail();
+	update_fwd_ports(RTE_MAX_ETHPORTS);
+}
+
 void
 close_port(portid_t pid)
 {
@@ -2315,7 +2339,6 @@ void
 detach_port(portid_t port_id)
 {
 	char name[RTE_ETH_NAME_MAX_LEN];
-	uint16_t i;
 
 	printf("Detaching a port...\n");
 
@@ -2332,16 +2355,7 @@ detach_port(portid_t port_id)
 		return;
 	}
 
-	for (i = 0; i < nb_ports; i++) {
-		if (ports_ids[i] == port_id) {
-			ports_ids[i] = ports_ids[nb_ports-1];
-			ports_ids[nb_ports-1] = 0;
-			break;
-		}
-	}
-	nb_ports = rte_eth_dev_count_avail();
-
-	update_fwd_ports(RTE_MAX_ETHPORTS);
+	remove_unused_fwd_ports();
 
 	printf("Port %u is detached. Now total ports is %d\n",
 			port_id, nb_ports);
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v5 2/6] app/testpmd: allow detaching a port not closed
  2018-10-18  1:23 ` [dpdk-dev] [PATCH v5 0/6] " Thomas Monjalon
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once Thomas Monjalon
@ 2018-10-18  1:23   ` Thomas Monjalon
  2018-10-18  7:45     ` Andrew Rybchenko
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 3/6] ethdev: fix doxygen comments of shared data fields Thomas Monjalon
                     ` (3 subsequent siblings)
  5 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:23 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

The testpmd application aim is for testing;
so order of operations should not be enforced.

There was a test to forbid detaching before closing a port.
However, it may interesting to test what happens in such case.
It is possible for a PMD to automatically close the port when detaching.

in order to avoid a crash, it is checked that the port must be stopped
before detaching (as for closing).

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index c4109417a..31aadec63 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2343,13 +2343,15 @@ detach_port(portid_t port_id)
 	printf("Detaching a port...\n");
 
 	if (!port_is_closed(port_id)) {
-		printf("Please close port first\n");
-		return;
+		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
+			printf("Port not stopped\n");
+			return;
+		}
+		printf("Port was not closed\n");
+		if (ports[port_id].flow_list)
+			port_flow_flush(port_id);
 	}
 
-	if (ports[port_id].flow_list)
-		port_flow_flush(port_id);
-
 	if (rte_eth_dev_detach(port_id, name)) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v5 3/6] ethdev: fix doxygen comments of shared data fields
  2018-10-18  1:23 ` [dpdk-dev] [PATCH v5 0/6] " Thomas Monjalon
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once Thomas Monjalon
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 2/6] app/testpmd: allow detaching a port not closed Thomas Monjalon
@ 2018-10-18  1:23   ` Thomas Monjalon
  2018-10-18  7:11     ` Andrew Rybchenko
  2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 4/6] ethdev: free all common data when releasing port Thomas Monjalon
                     ` (2 subsequent siblings)
  5 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:23 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

Some doxygen comments were wrongly associated to the next field
because of syntax /** instead of /**<

Some other cleanups (like alignment) are done.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 lib/librte_ethdev/rte_ethdev_core.h | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 33d12b3a2..03ec4992a 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -581,22 +581,20 @@ struct rte_eth_dev_data {
 
 	void *dev_private;              /**< PMD-specific private data */
 
-	struct rte_eth_link dev_link;
-	/**< Link-level information & status */
-
+	struct rte_eth_link dev_link;   /**< Link-level information & status. */
 	struct rte_eth_conf dev_conf;   /**< Configuration applied to device. */
 	uint16_t mtu;                   /**< Maximum Transmission Unit. */
-
 	uint32_t min_rx_buf_size;
-	/**< Common rx buffer size handled by all queues */
+			/**< Common RX buffer size handled by all queues. */
 
 	uint64_t rx_mbuf_alloc_failed; /**< RX ring mbuf allocation failures. */
-	struct ether_addr* mac_addrs;/**< Device Ethernet Link address. */
+	struct ether_addr *mac_addrs;  /**< Device Ethernet link address. */
 	uint64_t mac_pool_sel[ETH_NUM_RECEIVE_MAC_ADDR];
-	/** bitmap array of associating Ethernet MAC addresses to pools */
-	struct ether_addr* hash_mac_addrs;
-	/** Device Ethernet MAC addresses of hash filtering. */
+			/**< Bitmap associating MAC addresses to pools. */
+	struct ether_addr *hash_mac_addrs;
+			/**< Device Ethernet MAC addresses of hash filtering. */
 	uint16_t port_id;           /**< Device [external] port identifier. */
+
 	__extension__
 	uint8_t promiscuous   : 1, /**< RX promiscuous mode ON(1) / OFF(0). */
 		scattered_rx : 1,  /**< RX of scattered packets is ON(1) / OFF(0) */
@@ -604,14 +602,14 @@ struct rte_eth_dev_data {
 		dev_started : 1,   /**< Device state: STARTED(1) / STOPPED(0). */
 		lro         : 1;   /**< RX LRO is ON(1) / OFF(0) */
 	uint8_t rx_queue_state[RTE_MAX_QUEUES_PER_PORT];
-	/** Queues state: STARTED(1) / STOPPED(0) */
+			/**< Queues state: STARTED(1) / STOPPED(0). */
 	uint8_t tx_queue_state[RTE_MAX_QUEUES_PER_PORT];
-	/** Queues state: STARTED(1) / STOPPED(0) */
-	uint32_t dev_flags; /**< Capabilities */
-	enum rte_kernel_driver kdrv;    /**< Kernel driver passthrough */
-	int numa_node;  /**< NUMA node connection */
+			/**< Queues state: STARTED(1) / STOPPED(0). */
+	uint32_t dev_flags;             /**< Capabilities. */
+	enum rte_kernel_driver kdrv;    /**< Kernel driver passthrough. */
+	int numa_node;                  /**< NUMA node connection. */
 	struct rte_vlan_filter_conf vlan_filter_conf;
-	/**< VLAN filter configuration. */
+			/**< VLAN filter configuration. */
 	struct rte_eth_dev_owner owner; /**< The port owner. */
 } __rte_cache_aligned;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v5 4/6] ethdev: free all common data when releasing port
  2018-10-18  1:23 ` [dpdk-dev] [PATCH v5 0/6] " Thomas Monjalon
                     ` (2 preceding siblings ...)
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 3/6] ethdev: fix doxygen comments of shared data fields Thomas Monjalon
@ 2018-10-18  1:24   ` Thomas Monjalon
  2018-10-18  7:13     ` Andrew Rybchenko
  2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 5/6] ethdev: remove release function for secondary process Thomas Monjalon
  2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 6/6] ethdev: complete closing of port Thomas Monjalon
  5 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:24 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

This is a clean-up of common ethdev data freeing.
All data freeing are moved to rte_eth_dev_release_port()
and done only in case of primary process.

It is probably fixing some memory leaks for PMDs which were
not freeing all data.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/net/af_packet/rte_eth_af_packet.c |  5 ++--
 drivers/net/ark/ark_ethdev.c              |  1 -
 drivers/net/avf/avf_ethdev.c              |  3 ---
 drivers/net/avp/avp_ethdev.c              |  5 ----
 drivers/net/axgbe/axgbe_ethdev.c          |  3 ---
 drivers/net/bnxt/bnxt_ethdev.c            |  4 ----
 drivers/net/bonding/rte_eth_bond_pmd.c    |  9 +++----
 drivers/net/cxgbe/cxgbe_main.c            | 16 ++-----------
 drivers/net/cxgbe/cxgbevf_main.c          |  9 +------
 drivers/net/dpaa/dpaa_ethdev.c            | 10 --------
 drivers/net/dpaa2/dpaa2_ethdev.c          | 10 --------
 drivers/net/e1000/em_ethdev.c             |  3 ---
 drivers/net/e1000/igb_ethdev.c            |  6 -----
 drivers/net/enetc/enetc_ethdev.c          |  4 +---
 drivers/net/failsafe/failsafe.c           |  6 +++--
 drivers/net/fm10k/fm10k_ethdev.c          |  8 -------
 drivers/net/i40e/i40e_ethdev.c            |  3 ---
 drivers/net/i40e/i40e_ethdev_vf.c         |  3 ---
 drivers/net/i40e/i40e_vf_representor.c    |  5 +++-
 drivers/net/ixgbe/ixgbe_ethdev.c          |  9 -------
 drivers/net/ixgbe/ixgbe_vf_representor.c  |  5 +++-
 drivers/net/kni/rte_eth_kni.c             |  5 ++--
 drivers/net/liquidio/lio_ethdev.c         |  3 ---
 drivers/net/mlx4/mlx4.c                   |  7 +++++-
 drivers/net/mlx5/mlx5.c                   | 11 ++++++---
 drivers/net/mvneta/mvneta_ethdev.c        | 16 ++++---------
 drivers/net/mvpp2/mrvl_ethdev.c           | 16 ++++---------
 drivers/net/netvsc/hn_ethdev.c            | 15 ++----------
 drivers/net/null/rte_eth_null.c           |  4 ++--
 drivers/net/octeontx/octeontx_ethdev.c    | 29 +++++++++--------------
 drivers/net/pcap/rte_eth_pcap.c           |  8 +++----
 drivers/net/qede/qede_ethdev.c            |  5 ----
 drivers/net/ring/rte_eth_ring.c           |  6 ++---
 drivers/net/sfc/sfc_ethdev.c              |  3 ---
 drivers/net/softnic/rte_eth_softnic.c     |  7 +++---
 drivers/net/szedata2/rte_eth_szedata2.c   |  1 -
 drivers/net/tap/rte_eth_tap.c             |  6 ++++-
 drivers/net/vhost/rte_eth_vhost.c         |  9 +++----
 drivers/net/virtio/virtio_ethdev.c        |  3 ---
 drivers/net/virtio/virtio_user_ethdev.c   |  3 ---
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  3 ---
 lib/librte_ethdev/rte_ethdev.c            | 21 ++++++++--------
 lib/librte_ethdev/rte_ethdev_core.h       | 14 ++++++++---
 lib/librte_ethdev/rte_ethdev_driver.h     |  9 ++++++-
 lib/librte_ethdev/rte_ethdev_pci.h        | 10 --------
 45 files changed, 109 insertions(+), 232 deletions(-)

diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 376d76302..2efc17725 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -986,6 +986,9 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
@@ -996,8 +999,6 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	}
 	free(internals->if_name);
 
-	rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index 552ca01a6..70d62ec7f 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -506,7 +506,6 @@ eth_ark_dev_uninit(struct rte_eth_dev *dev)
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
-	rte_free(dev->data->mac_addrs);
 	return 0;
 }
 
diff --git a/drivers/net/avf/avf_ethdev.c b/drivers/net/avf/avf_ethdev.c
index e56d57c43..13eec1b45 100644
--- a/drivers/net/avf/avf_ethdev.c
+++ b/drivers/net/avf/avf_ethdev.c
@@ -1303,9 +1303,6 @@ avf_dev_uninit(struct rte_eth_dev *dev)
 	rte_free(vf->aq_resp);
 	vf->aq_resp = NULL;
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	if (vf->rss_lut) {
 		rte_free(vf->rss_lut);
 		vf->rss_lut = NULL;
diff --git a/drivers/net/avp/avp_ethdev.c b/drivers/net/avp/avp_ethdev.c
index 0f8ccb954..09388d05f 100644
--- a/drivers/net/avp/avp_ethdev.c
+++ b/drivers/net/avp/avp_ethdev.c
@@ -1036,11 +1036,6 @@ eth_avp_dev_uninit(struct rte_eth_dev *eth_dev)
 		return ret;
 	}
 
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index 4b84b50c0..e89c0ec2c 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -718,9 +718,6 @@ eth_axgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 		return 0;
 
 	pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
-	/*Free macaddres*/
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c11fe9c8c..801c6ffad 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -3501,10 +3501,6 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev)
 	bnxt_disable_int(bp);
 	bnxt_free_int(bp);
 	bnxt_free_mem(bp);
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
 	if (bp->grp_info != NULL) {
 		rte_free(bp->grp_info);
 		bp->grp_info = NULL;
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index b731132a5..77fb3dcd3 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3128,10 +3128,9 @@ bond_alloc(struct rte_vdev_device *dev, uint8_t mode)
 
 err:
 	rte_free(internals);
-	if (eth_dev != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		rte_eth_dev_release_port(eth_dev);
-	}
+	if (eth_dev != NULL)
+		eth_dev->data->dev_private = NULL;
+	rte_eth_dev_release_port(eth_dev);
 	return -1;
 }
 
@@ -3292,8 +3291,6 @@ bond_remove(struct rte_vdev_device *dev)
 	rte_mempool_free(internals->mode6.mempool);
 	rte_bitmap_free(internals->vlan_filter_bmp);
 	rte_free(internals->vlan_filter_bmpmem);
-	rte_free(eth_dev->data->dev_private);
-	rte_free(eth_dev->data->mac_addrs);
 
 	rte_eth_dev_release_port(eth_dev);
 
diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
index a135df9c7..88dc851f8 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -1710,12 +1710,7 @@ void cxgbe_close(struct adapter *adapter)
 			if (pi->viid != 0)
 				t4_free_vi(adapter, adapter->mbox,
 					   adapter->pf, 0, pi->viid);
-			rte_free(pi->eth_dev->data->mac_addrs);
-			/* Skip first port since it'll be freed by DPDK stack */
-			if (i) {
-				rte_free(pi->eth_dev->data->dev_private);
-				rte_eth_dev_release_port(pi->eth_dev);
-			}
+			rte_eth_dev_release_port(pi->eth_dev);
 		}
 		adapter->flags &= ~FULL_INIT_DONE;
 	}
@@ -1918,14 +1913,7 @@ int cxgbe_probe(struct adapter *adapter)
 		if (pi->viid != 0)
 			t4_free_vi(adapter, adapter->mbox, adapter->pf,
 				   0, pi->viid);
-		/* Skip first port since it'll be de-allocated by DPDK */
-		if (i == 0)
-			continue;
-		if (pi->eth_dev) {
-			if (pi->eth_dev->data->dev_private)
-				rte_free(pi->eth_dev->data->dev_private);
-			rte_eth_dev_release_port(pi->eth_dev);
-		}
+		rte_eth_dev_release_port(pi->eth_dev);
 	}
 
 	if (adapter->flags & FW_OK)
diff --git a/drivers/net/cxgbe/cxgbevf_main.c b/drivers/net/cxgbe/cxgbevf_main.c
index 4214d0312..6223e1250 100644
--- a/drivers/net/cxgbe/cxgbevf_main.c
+++ b/drivers/net/cxgbe/cxgbevf_main.c
@@ -282,14 +282,7 @@ int cxgbevf_probe(struct adapter *adapter)
 		if (pi->viid != 0)
 			t4_free_vi(adapter, adapter->mbox, adapter->pf,
 				   0, pi->viid);
-		/* Skip first port since it'll be de-allocated by DPDK */
-		if (i == 0)
-			continue;
-		if (pi->eth_dev) {
-			if (pi->eth_dev->data->dev_private)
-				rte_free(pi->eth_dev->data->dev_private);
-			rte_eth_dev_release_port(pi->eth_dev);
-		}
+		rte_eth_dev_release_port(pi->eth_dev);
 	}
 	return -err;
 }
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 5c743c3c8..d0572b3d9 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1439,10 +1439,6 @@ dpaa_dev_uninit(struct rte_eth_dev *dev)
 	rte_free(dpaa_intf->tx_queues);
 	dpaa_intf->tx_queues = NULL;
 
-	/* free memory for storing MAC addresses */
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
@@ -1544,9 +1540,6 @@ rte_dpaa_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused,
 		return 0;
 	}
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 	return diag;
 }
@@ -1561,9 +1554,6 @@ rte_dpaa_remove(struct rte_dpaa_device *dpaa_dev)
 	eth_dev = dpaa_dev->eth_dev;
 	dpaa_dev_uninit(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 3987d13df..8267ee3f0 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -2065,12 +2065,6 @@ dpaa2_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	dpaa2_free_rx_tx_queues(eth_dev);
 
-	/* free memory for storing MAC addresses */
-	if (eth_dev->data->mac_addrs) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
-
 	/* Close the device at underlying layer*/
 	ret = dpni_close(dpni, CMD_PRI_LOW, priv->token);
 	if (ret) {
@@ -2133,8 +2127,6 @@ rte_dpaa2_probe(struct rte_dpaa2_driver *dpaa2_drv,
 		return 0;
 	}
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 	return diag;
 }
@@ -2147,8 +2139,6 @@ rte_dpaa2_remove(struct rte_dpaa2_device *dpaa2_dev)
 	eth_dev = dpaa2_dev->eth_dev;
 	dpaa2_dev_uninit(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 28c153512..8230824e7 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -329,9 +329,6 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(intr_handle);
 	rte_intr_callback_unregister(intr_handle,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e542ef572..d9d29d22f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -917,9 +917,6 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* Reset any pending lock */
 	igb_reset_swfw_lock(hw);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* uninitialize PF if max_vfs not zero */
 	igb_pf_host_uninit(eth_dev);
 
@@ -1073,9 +1070,6 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(&pci_dev->intr_handle);
 	rte_intr_callback_unregister(&pci_dev->intr_handle,
diff --git a/drivers/net/enetc/enetc_ethdev.c b/drivers/net/enetc/enetc_ethdev.c
index 3ee7bb446..023fe7517 100644
--- a/drivers/net/enetc/enetc_ethdev.c
+++ b/drivers/net/enetc/enetc_ethdev.c
@@ -108,11 +108,9 @@ enetc_dev_init(struct rte_eth_dev *eth_dev)
 }
 
 static int
-enetc_dev_uninit(struct rte_eth_dev *eth_dev)
+enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused)
 {
 	PMD_INIT_FUNC_TRACE();
-	rte_free(eth_dev->data->mac_addrs);
-
 	return 0;
 }
 
diff --git a/drivers/net/failsafe/failsafe.c b/drivers/net/failsafe/failsafe.c
index c3999f026..fed36da5f 100644
--- a/drivers/net/failsafe/failsafe.c
+++ b/drivers/net/failsafe/failsafe.c
@@ -280,7 +280,8 @@ fs_eth_dev_create(struct rte_vdev_device *vdev)
 free_subs:
 	fs_sub_device_free(dev);
 free_dev:
-	rte_free(PRIV(dev));
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(dev);
 	return -1;
 }
@@ -305,7 +306,8 @@ fs_rte_eth_free(const char *name)
 	if (ret)
 		ERROR("Error while destroying hotplug mutex");
 	rte_free(PRIV(dev)->mcast_addrs);
-	rte_free(PRIV(dev));
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(dev);
 	return ret;
 }
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 46983e5df..bb7b906a9 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3234,14 +3234,6 @@ eth_fm10k_dev_uninit(struct rte_eth_dev *dev)
 			fm10k_dev_interrupt_handler_vf, (void *)dev);
 	}
 
-	/* free mac memory */
-	if (dev->data->mac_addrs) {
-		rte_free(dev->data->mac_addrs);
-		dev->data->mac_addrs = NULL;
-	}
-
-	memset(hw, 0, sizeof(*hw));
-
 	return 0;
 }
 
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index f7a685c8c..8a5c3c8fb 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1728,9 +1728,6 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	/* uninitialize pf host driver */
 	i40e_pf_host_uninit(dev);
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(intr_handle);
 
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index baa6cc58f..ed2fc1310 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1483,9 +1483,6 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
 		return -1;
 	}
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/i40e/i40e_vf_representor.c b/drivers/net/i40e/i40e_vf_representor.c
index 24751d13c..43fe00cca 100644
--- a/drivers/net/i40e/i40e_vf_representor.c
+++ b/drivers/net/i40e/i40e_vf_representor.c
@@ -523,7 +523,10 @@ i40e_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params)
 }
 
 int
-i40e_vf_representor_uninit(struct rte_eth_dev *ethdev __rte_unused)
+i40e_vf_representor_uninit(struct rte_eth_dev *ethdev)
 {
+	/* mac_addrs must not be freed because part of i40e_pf_vf */
+	ethdev->data->mac_addrs = NULL;
+
 	return 0;
 }
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index c458bffc0..269595b73 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1337,12 +1337,6 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* uninitialize PF if max_vfs not zero */
 	ixgbe_pf_host_uninit(eth_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
-	rte_free(eth_dev->data->hash_mac_addrs);
-	eth_dev->data->hash_mac_addrs = NULL;
-
 	/* remove all the fdir filters & hash */
 	ixgbe_fdir_filter_uninit(eth_dev);
 
@@ -1722,9 +1716,6 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* Disable the interrupts for VF */
 	ixgbevf_intr_disable(eth_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	rte_intr_disable(intr_handle);
 	rte_intr_callback_unregister(intr_handle,
 				     ixgbevf_dev_interrupt_handler, eth_dev);
diff --git a/drivers/net/ixgbe/ixgbe_vf_representor.c b/drivers/net/ixgbe/ixgbe_vf_representor.c
index b0fbbc49f..eb9bbe5cb 100644
--- a/drivers/net/ixgbe/ixgbe_vf_representor.c
+++ b/drivers/net/ixgbe/ixgbe_vf_representor.c
@@ -225,7 +225,10 @@ ixgbe_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params)
 }
 
 int
-ixgbe_vf_representor_uninit(struct rte_eth_dev *ethdev __rte_unused)
+ixgbe_vf_representor_uninit(struct rte_eth_dev *ethdev)
 {
+	/* mac_addrs must not be freed because part of ixgbe_vf_info */
+	ethdev->data->mac_addrs = NULL;
+
 	return 0;
 }
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 72f3c16c1..f43ee7d2e 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -463,6 +463,9 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	if (eth_dev == NULL)
 		return -1;
 
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
@@ -471,8 +474,6 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	internals = eth_dev->data->dev_private;
 	rte_kni_release(internals->kni);
 
-	rte_free(internals);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	is_kni_initialized--;
diff --git a/drivers/net/liquidio/lio_ethdev.c b/drivers/net/liquidio/lio_ethdev.c
index 0f59e4475..d13ab06c0 100644
--- a/drivers/net/liquidio/lio_ethdev.c
+++ b/drivers/net/liquidio/lio_ethdev.c
@@ -2043,9 +2043,6 @@ lio_eth_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* lio_free_sc_buffer_pool */
 	lio_free_sc_buffer_pool(lio_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 3de7bc53e..7f07b8dc0 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -781,12 +781,17 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 		continue;
 port_error:
 		rte_free(priv);
+		if (eth_dev != NULL)
+			eth_dev->data->dev_private = NULL;
 		if (pd)
 			claim_zero(mlx4_glue->dealloc_pd(pd));
 		if (ctx)
 			claim_zero(mlx4_glue->close_device(ctx));
-		if (eth_dev)
+		if (eth_dev != NULL) {
+			/* mac_addrs must not be freed because part of dev_private */
+			eth_dev->data->mac_addrs = NULL;
 			rte_eth_dev_release_port(eth_dev);
+		}
 		break;
 	}
 	/*
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 8cbfee1ba..b2be74b51 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1223,11 +1223,16 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		if (own_domain_id)
 			claim_zero(rte_eth_switch_domain_free(priv->domain_id));
 		rte_free(priv);
+		if (eth_dev != NULL)
+			eth_dev->data->dev_private = NULL;
 	}
 	if (pd)
 		claim_zero(mlx5_glue->dealloc_pd(pd));
-	if (eth_dev)
+	if (eth_dev != NULL) {
+		/* mac_addrs must not be freed alone because part of dev_private */
+		eth_dev->data->mac_addrs = NULL;
 		rte_eth_dev_release_port(eth_dev);
+	}
 	if (ctx)
 		claim_zero(mlx5_glue->close_device(ctx));
 	assert(err > 0);
@@ -1447,8 +1452,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 			if (!list[i].eth_dev)
 				continue;
 			mlx5_dev_close(list[i].eth_dev);
-			if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-				rte_free(list[i].eth_dev->data->dev_private);
+			/* mac_addrs must not be freed because in dev_private */
+			list[i].eth_dev->data->mac_addrs = NULL;
 			claim_zero(rte_eth_dev_release_port(list[i].eth_dev));
 		}
 		/* Restore original error. */
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index f7071bc2e..2d7666454 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -787,8 +787,9 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	priv = rte_zmalloc_socket(name, sizeof(*priv), 0, rte_socket_id());
 	if (!priv) {
 		ret = -ENOMEM;
-		goto out_free_dev;
+		goto out_free;
 	}
+	eth_dev->data->dev_private = priv;
 
 	eth_dev->data->mac_addrs =
 		rte_zmalloc("mac_addrs",
@@ -796,20 +797,19 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	if (!eth_dev->data->mac_addrs) {
 		MVNETA_LOG(ERR, "Failed to allocate space for eth addrs");
 		ret = -ENOMEM;
-		goto out_free_priv;
+		goto out_free;
 	}
 
 	memset(&req, 0, sizeof(req));
 	strcpy(req.ifr_name, name);
 	ret = ioctl(fd, SIOCGIFHWADDR, &req);
 	if (ret)
-		goto out_free_mac;
+		goto out_free;
 
 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
 
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
-	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
 	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
 	mvneta_set_tx_function(eth_dev);
@@ -817,11 +817,7 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 
 	rte_eth_dev_probing_finish(eth_dev);
 	return 0;
-out_free_mac:
-	rte_free(eth_dev->data->mac_addrs);
-out_free_priv:
-	rte_free(priv);
-out_free_dev:
+out_free:
 	rte_eth_dev_release_port(eth_dev);
 
 	return ret;
@@ -836,8 +832,6 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 static void
 mvneta_eth_dev_destroy(struct rte_eth_dev *eth_dev)
 {
-	rte_free(eth_dev->data->dev_private);
-	rte_free(eth_dev->data->mac_addrs);
 	rte_eth_dev_release_port(eth_dev);
 }
 
diff --git a/drivers/net/mvpp2/mrvl_ethdev.c b/drivers/net/mvpp2/mrvl_ethdev.c
index 0682c635a..ab4c14e51 100644
--- a/drivers/net/mvpp2/mrvl_ethdev.c
+++ b/drivers/net/mvpp2/mrvl_ethdev.c
@@ -2780,8 +2780,9 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	priv = mrvl_priv_create(name);
 	if (!priv) {
 		ret = -ENOMEM;
-		goto out_free_dev;
+		goto out_free;
 	}
+	eth_dev->data->dev_private = priv;
 
 	eth_dev->data->mac_addrs =
 		rte_zmalloc("mac_addrs",
@@ -2789,20 +2790,19 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	if (!eth_dev->data->mac_addrs) {
 		MRVL_LOG(ERR, "Failed to allocate space for eth addrs");
 		ret = -ENOMEM;
-		goto out_free_priv;
+		goto out_free;
 	}
 
 	memset(&req, 0, sizeof(req));
 	strcpy(req.ifr_name, name);
 	ret = ioctl(fd, SIOCGIFHWADDR, &req);
 	if (ret)
-		goto out_free_mac;
+		goto out_free;
 
 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
 
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
-	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
 	eth_dev->rx_pkt_burst = mrvl_rx_pkt_burst;
 	mrvl_set_tx_function(eth_dev);
@@ -2810,12 +2810,8 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 
 	rte_eth_dev_probing_finish(eth_dev);
 	return 0;
-out_free_mac:
-	rte_free(eth_dev->data->mac_addrs);
-out_free_dev:
+out_free:
 	rte_eth_dev_release_port(eth_dev);
-out_free_priv:
-	rte_free(priv);
 
 	return ret;
 }
@@ -2839,8 +2835,6 @@ mrvl_eth_dev_destroy(const char *name)
 	priv = eth_dev->data->dev_private;
 	pp2_bpool_deinit(priv->bpool);
 	used_bpools[priv->pp_id] &= ~(1 << priv->bpool_bit);
-	rte_free(priv);
-	rte_free(eth_dev->data->mac_addrs);
 	rte_eth_dev_release_port(eth_dev);
 }
 
diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c
index 8e728d639..aa38ee7a3 100644
--- a/drivers/net/netvsc/hn_ethdev.c
+++ b/drivers/net/netvsc/hn_ethdev.c
@@ -118,20 +118,11 @@ eth_dev_vmbus_allocate(struct rte_vmbus_device *dev, size_t private_data_size)
 static void
 eth_dev_vmbus_release(struct rte_eth_dev *eth_dev)
 {
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
 	/* free ether device */
 	rte_eth_dev_release_port(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
-	eth_dev->data->dev_private = NULL;
-
-	/*
-	 * Secondary process will check the name to attach.
-	 * Clear this field to avoid attaching a released ports.
-	 */
-	eth_dev->data->name[0] = '\0';
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 }
@@ -829,8 +820,6 @@ eth_hn_dev_uninit(struct rte_eth_dev *eth_dev)
 	rte_free(hv->primary);
 	rte_eth_dev_owner_delete(hv->owner.id);
 
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index 1e8237a41..b77283ae7 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -682,8 +682,8 @@ rte_pmd_null_remove(struct rte_vdev_device *dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
-	rte_free(eth_dev->data->dev_private);
-
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index 5431b44dc..746507912 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -1015,12 +1015,22 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 		return 0;
 	}
 
+	/* Reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(octtx_name);
+	if (eth_dev == NULL) {
+		octeontx_log_err("failed to allocate rte_eth_dev");
+		res = -ENOMEM;
+		goto err;
+	}
+	data = eth_dev->data;
+
 	nic = rte_zmalloc_socket(octtx_name, sizeof(*nic), 0, socket_id);
 	if (nic == NULL) {
 		octeontx_log_err("failed to allocate nic structure");
 		res = -ENOMEM;
 		goto err;
 	}
+	data->dev_private = nic;
 
 	nic->port_id = port;
 	nic->evdev = evdev;
@@ -1037,21 +1047,11 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 		goto err;
 	}
 
-	/* Reserve an ethdev entry */
-	eth_dev = rte_eth_dev_allocate(octtx_name);
-	if (eth_dev == NULL) {
-		octeontx_log_err("failed to allocate rte_eth_dev");
-		res = -ENOMEM;
-		goto err;
-	}
-
 	eth_dev->device = &dev->device;
 	eth_dev->intr_handle = NULL;
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->numa_node = dev->device.numa_node;
 
-	data = eth_dev->data;
-	data->dev_private = nic;
 	data->port_id = eth_dev->data->port_id;
 
 	nic->ev_queues = 1;
@@ -1103,12 +1103,7 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 	if (nic)
 		octeontx_port_close(nic);
 
-	if (eth_dev != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		rte_free(data);
-		rte_free(nic);
-		rte_eth_dev_release_port(eth_dev);
-	}
+	rte_eth_dev_release_port(eth_dev);
 
 	return res;
 }
@@ -1142,8 +1137,6 @@ octeontx_remove(struct rte_vdev_device *dev)
 		rte_event_dev_stop(nic->evdev);
 		PMD_INIT_LOG(INFO, "Closing octeontx device %s", octtx_name);
 
-		rte_free(eth_dev->data->mac_addrs);
-		rte_free(eth_dev->data->dev_private);
 		rte_eth_dev_release_port(eth_dev);
 		rte_event_dev_close(nic->evdev);
 	}
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index ede5ebb45..1790a8064 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -1232,11 +1232,9 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
 	internals = eth_dev->data->dev_private;
-	if (internals && internals->phy_mac)
-		rte_free(eth_dev->data->mac_addrs);
-
-	rte_free(eth_dev->data->dev_private);
-
+	if (internals != NULL && internals->phy_mac == 0)
+		/* not dynamically allocated, must not be freed */
+		eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 18d244a93..404859426 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2666,11 +2666,6 @@ static int qede_dev_common_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	if (eth_dev->data->mac_addrs)
-		rte_free(eth_dev->data->mac_addrs);
-
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/ring/rte_eth_ring.c b/drivers/net/ring/rte_eth_ring.c
index bfe2f1780..aeb48f5ec 100644
--- a/drivers/net/ring/rte_eth_ring.c
+++ b/drivers/net/ring/rte_eth_ring.c
@@ -666,10 +666,8 @@ rte_pmd_ring_remove(struct rte_vdev_device *dev)
 		}
 	}
 
-	rte_free(eth_dev->data->rx_queues);
-	rte_free(eth_dev->data->tx_queues);
-	rte_free(eth_dev->data->dev_private);
-
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 	return 0;
 }
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index b2e17f26e..3886daf7a 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -2035,9 +2035,6 @@ sfc_eth_dev_uninit(struct rte_eth_dev *dev)
 	sfc_detach(sa);
 	sfc_unprobe(sa);
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	sfc_kvargs_cleanup(sa);
 
 	sfc_adapter_unlock(sa);
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 0fd264e25..9a2418438 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -556,7 +556,6 @@ static int
 pmd_remove(struct rte_vdev_device *vdev)
 {
 	struct rte_eth_dev *dev = NULL;
-	struct pmd_internals *p;
 
 	if (!vdev)
 		return -EINVAL;
@@ -567,12 +566,12 @@ pmd_remove(struct rte_vdev_device *vdev)
 	dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
 	if (dev == NULL)
 		return -ENODEV;
-	p = dev->data->dev_private;
 
 	/* Free device data structures*/
-	rte_free(dev->data);
+	pmd_free(dev->data->dev_private);
+	dev->data->dev_private = NULL; /* already freed */
+	dev->data->mac_addrs = NULL; /* statically allocated */
 	rte_eth_dev_release_port(dev);
-	pmd_free(p);
 
 	return 0;
 }
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index 4e5e01cf1..88448eff6 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1544,7 +1544,6 @@ rte_szedata2_eth_dev_uninit(struct rte_eth_dev *dev)
 	PMD_INIT_FUNC_TRACE();
 
 	free(internals->sze_dev_path);
-	rte_free(dev->data->mac_addrs);
 
 	PMD_DRV_LOG(INFO, "%s device %s successfully uninitialized",
 			RTE_STR(RTE_SZEDATA2_DRIVER_NAME), dev->data->name);
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 84aaf2410..2327fbf8c 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1808,6 +1808,8 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, char *tap_name,
 error_exit:
 	if (pmd->ioctl_sock > 0)
 		close(pmd->ioctl_sock);
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(dev);
 
 error_exit_nodev:
@@ -2076,6 +2078,9 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	if (!eth_dev)
 		return -ENODEV;
 
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
@@ -2102,7 +2107,6 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	}
 
 	close(internals->ioctl_sock);
-	rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	if (internals->ka_fd != -1) {
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index a7604ff23..cf51c072d 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -1220,10 +1220,12 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internal));
 	if (eth_dev == NULL)
 		goto error;
+	data = eth_dev->data;
 
 	eth_addr = rte_zmalloc_socket(name, sizeof(*eth_addr), 0, numa_node);
 	if (eth_addr == NULL)
 		goto error;
+	data->mac_addrs = eth_addr;
 	*eth_addr = base_eth_addr;
 	eth_addr->addr_bytes[5] = eth_dev->data->port_id;
 
@@ -1253,13 +1255,11 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
 
-	data = eth_dev->data;
 	data->nb_rx_queues = queues;
 	data->nb_tx_queues = queues;
 	internal->max_queues = queues;
 	internal->vid = -1;
 	data->dev_link = pmd_link;
-	data->mac_addrs = eth_addr;
 	data->dev_flags = RTE_ETH_DEV_INTR_LSC;
 
 	eth_dev->dev_ops = &ops;
@@ -1291,10 +1291,7 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 		free(internal->dev_name);
 	}
 	rte_free(vring_state);
-	rte_free(eth_addr);
-	if (eth_dev)
-		rte_eth_dev_release_port(eth_dev);
-	rte_free(internal);
+	rte_eth_dev_release_port(eth_dev);
 	rte_free(list);
 
 	return -1;
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 730c41707..10a7e3fcc 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1706,9 +1706,6 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->tx_pkt_burst = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* reset interrupt callback  */
 	if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
 		rte_intr_callback_unregister(eth_dev->intr_handle,
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 525d16cab..420364b7a 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -422,7 +422,6 @@ virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev)
 	if (!dev) {
 		PMD_INIT_LOG(ERR, "malloc virtio_user_dev failed");
 		rte_eth_dev_release_port(eth_dev);
-		rte_free(hw);
 		return NULL;
 	}
 
@@ -449,7 +448,6 @@ virtio_user_eth_dev_free(struct rte_eth_dev *eth_dev)
 	struct virtio_hw *hw = data->dev_private;
 
 	rte_free(hw->virtio_user_dev);
-	rte_free(hw);
 	rte_eth_dev_release_port(eth_dev);
 }
 
@@ -662,7 +660,6 @@ virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 	dev = hw->virtio_user_dev;
 	virtio_user_dev_uninit(dev);
 
-	rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 78e5b7680..41bcd450a 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -368,9 +368,6 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->tx_pkt_burst = NULL;
 	eth_dev->tx_pkt_prepare = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 571f0e850..3bc05f4c3 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -388,7 +388,14 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 
 	eth_dev->state = RTE_ETH_DEV_UNUSED;
 
-	memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		rte_free(eth_dev->data->rx_queues);
+		rte_free(eth_dev->data->tx_queues);
+		rte_free(eth_dev->data->mac_addrs);
+		rte_free(eth_dev->data->hash_mac_addrs);
+		rte_free(eth_dev->data->dev_private);
+		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
+	}
 
 	rte_spinlock_unlock(&rte_eth_dev_shared_data->ownership_lock);
 
@@ -3529,7 +3536,7 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 			if (!ethdev->data->dev_private) {
 				RTE_LOG(ERR, EAL, "failed to allocate private data");
 				retval = -ENOMEM;
-				goto data_alloc_failed;
+				goto probe_failed;
 			}
 		}
 	} else {
@@ -3561,14 +3568,9 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 	rte_eth_dev_probing_finish(ethdev);
 
 	return retval;
-probe_failed:
-	/* free ports private data if primary process */
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(ethdev->data->dev_private);
 
-data_alloc_failed:
+probe_failed:
 	rte_eth_dev_release_port(ethdev);
-
 	return retval;
 }
 
@@ -3592,9 +3594,6 @@ rte_eth_dev_destroy(struct rte_eth_dev *ethdev,
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(ethdev);
 
-	rte_free(ethdev->data->dev_private);
-	ethdev->data->dev_private = NULL;
-
 	return rte_eth_dev_release_port(ethdev);
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 03ec4992a..9fb826e1d 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -579,7 +579,10 @@ struct rte_eth_dev_data {
 
 	struct rte_eth_dev_sriov sriov;    /**< SRIOV data */
 
-	void *dev_private;              /**< PMD-specific private data */
+	void *dev_private;
+			/**< PMD-specific private data.
+			 *   @see rte_eth_dev_release_port()
+			 */
 
 	struct rte_eth_link dev_link;   /**< Link-level information & status. */
 	struct rte_eth_conf dev_conf;   /**< Configuration applied to device. */
@@ -588,11 +591,16 @@ struct rte_eth_dev_data {
 			/**< Common RX buffer size handled by all queues. */
 
 	uint64_t rx_mbuf_alloc_failed; /**< RX ring mbuf allocation failures. */
-	struct ether_addr *mac_addrs;  /**< Device Ethernet link address. */
+	struct ether_addr *mac_addrs;
+			/**< Device Ethernet link address.
+			 *   @see rte_eth_dev_release_port()
+			 */
 	uint64_t mac_pool_sel[ETH_NUM_RECEIVE_MAC_ADDR];
 			/**< Bitmap associating MAC addresses to pools. */
 	struct ether_addr *hash_mac_addrs;
-			/**< Device Ethernet MAC addresses of hash filtering. */
+			/**< Device Ethernet MAC addresses of hash filtering.
+			 *   @see rte_eth_dev_release_port()
+			 */
 	uint16_t port_id;           /**< Device [external] port identifier. */
 
 	__extension__
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index ca31b5777..66274be7a 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -58,7 +58,14 @@ struct rte_eth_dev *rte_eth_dev_attach_secondary(const char *name);
 
 /**
  * @internal
- * Release the specified ethdev port.
+ * Notify RTE_ETH_EVENT_DESTROY and release the specified ethdev port.
+ *
+ * The following PMD-managed data fields will be freed:
+ *   - dev_private
+ *   - mac_addrs
+ *   - hash_mac_addrs
+ * If one of these fields should not be freed,
+ * it must be reset to NULL by the PMD, typically in dev_close method.
  *
  * @param eth_dev
  * Device to be detached.
diff --git a/lib/librte_ethdev/rte_ethdev_pci.h b/lib/librte_ethdev/rte_ethdev_pci.h
index 70d2d2503..8ff4f6b89 100644
--- a/lib/librte_ethdev/rte_ethdev_pci.h
+++ b/lib/librte_ethdev/rte_ethdev_pci.h
@@ -142,16 +142,6 @@ rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev)
 		return;
 	}
 
-	/* primary process */
-	rte_free(eth_dev->data->dev_private);
-	eth_dev->data->dev_private = NULL;
-
-	/*
-	 * Secondary process will check the name to attach.
-	 * Clear this field to avoid attaching a released ports.
-	 */
-	eth_dev->data->name[0] = '\0';
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v5 5/6] ethdev: remove release function for secondary process
  2018-10-18  1:23 ` [dpdk-dev] [PATCH v5 0/6] " Thomas Monjalon
                     ` (3 preceding siblings ...)
  2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 4/6] ethdev: free all common data when releasing port Thomas Monjalon
@ 2018-10-18  1:24   ` Thomas Monjalon
  2018-10-18  7:15     ` Andrew Rybchenko
  2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 6/6] ethdev: complete closing of port Thomas Monjalon
  5 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:24 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

After previous changes, the function rte_eth_dev_release_port()
can be used for primary or secondary process as well.
The only difference with rte_eth_dev_release_port_secondary()
is the shared lock used in rte_eth_dev_release_port().

The function rte_eth_dev_release_port_secondary() was recently
added in 18.11 cycle.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/net/af_packet/rte_eth_af_packet.c |  2 +-
 drivers/net/bonding/rte_eth_bond_pmd.c    |  2 +-
 drivers/net/kni/rte_eth_kni.c             |  2 +-
 drivers/net/null/rte_eth_null.c           |  7 +++----
 drivers/net/octeontx/octeontx_ethdev.c    |  2 +-
 drivers/net/pcap/rte_eth_pcap.c           | 12 ++++++------
 drivers/net/tap/rte_eth_tap.c             |  2 +-
 drivers/net/vhost/rte_eth_vhost.c         |  2 +-
 lib/librte_ethdev/rte_ethdev.c            | 15 ---------------
 lib/librte_ethdev/rte_ethdev_driver.h     | 14 --------------
 lib/librte_ethdev/rte_ethdev_pci.h        |  7 -------
 lib/librte_ethdev/rte_ethdev_version.map  |  7 -------
 12 files changed, 15 insertions(+), 59 deletions(-)

diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 2efc17725..95a98c6b8 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -990,7 +990,7 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	eth_dev->data->mac_addrs = NULL;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	internals = eth_dev->data->dev_private;
 	for (q = 0; q < internals->nb_queues; q++) {
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 77fb3dcd3..e7a4be921 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3267,7 +3267,7 @@ bond_remove(struct rte_vdev_device *dev)
 		return -ENODEV;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	RTE_ASSERT(eth_dev->device == &dev->device);
 
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index f43ee7d2e..a1e9970df 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -467,7 +467,7 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	eth_dev->data->mac_addrs = NULL;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	eth_kni_dev_stop(eth_dev);
 
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index b77283ae7..159c1c1fd 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -679,11 +679,10 @@ rte_pmd_null_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		/* mac_addrs must not be freed alone because part of dev_private */
+		eth_dev->data->mac_addrs = NULL;
 
-	/* mac_addrs must not be freed alone because part of dev_private */
-	eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index 746507912..068148624 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -1129,7 +1129,7 @@ octeontx_remove(struct rte_vdev_device *dev)
 			return -ENODEV;
 
 		if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
-			rte_eth_dev_release_port_secondary(eth_dev);
+			rte_eth_dev_release_port(eth_dev);
 			continue;
 		}
 
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 1790a8064..7bbe72e25 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -1228,13 +1228,13 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		internals = eth_dev->data->dev_private;
+		if (internals != NULL && internals->phy_mac == 0)
+			/* not dynamically allocated, must not be freed */
+			eth_dev->data->mac_addrs = NULL;
+	}
 
-	internals = eth_dev->data->dev_private;
-	if (internals != NULL && internals->phy_mac == 0)
-		/* not dynamically allocated, must not be freed */
-		eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 2327fbf8c..53d37b3cb 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -2082,7 +2082,7 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	eth_dev->data->mac_addrs = NULL;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	internals = eth_dev->data->dev_private;
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index cf51c072d..0cd1a4642 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -1433,7 +1433,7 @@ rte_pmd_vhost_remove(struct rte_vdev_device *dev)
 		return -ENODEV;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	eth_dev_close(eth_dev);
 
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 3bc05f4c3..178800a5b 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -362,18 +362,6 @@ rte_eth_dev_attach_secondary(const char *name)
 	return eth_dev;
 }
 
-int
-rte_eth_dev_release_port_secondary(struct rte_eth_dev *eth_dev)
-{
-	if (eth_dev == NULL)
-		return -EINVAL;
-
-	_rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_DESTROY, NULL);
-	eth_dev->state = RTE_ETH_DEV_UNUSED;
-
-	return 0;
-}
-
 int
 rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 {
@@ -3591,9 +3579,6 @@ rte_eth_dev_destroy(struct rte_eth_dev *ethdev,
 			return ret;
 	}
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(ethdev);
-
 	return rte_eth_dev_release_port(ethdev);
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index 66274be7a..c2ac26328 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -74,20 +74,6 @@ struct rte_eth_dev *rte_eth_dev_attach_secondary(const char *name);
  */
 int rte_eth_dev_release_port(struct rte_eth_dev *eth_dev);
 
-/**
- * @internal
- * Release the specified ethdev port in the local process.
- * Only set ethdev state to unused, but not reset shared data since
- * it assume other processes is still using it. typically it is
- * called by a secondary process.
- *
- * @param eth_dev
- * Device to be detached.
- * @return
- *   - 0 on success, negative on error
- */
-int rte_eth_dev_release_port_secondary(struct rte_eth_dev *eth_dev);
-
 /**
  * @internal
  * Release device queues and clear its configuration to force the user
diff --git a/lib/librte_ethdev/rte_ethdev_pci.h b/lib/librte_ethdev/rte_ethdev_pci.h
index 8ff4f6b89..23257e986 100644
--- a/lib/librte_ethdev/rte_ethdev_pci.h
+++ b/lib/librte_ethdev/rte_ethdev_pci.h
@@ -135,13 +135,6 @@ rte_eth_dev_pci_allocate(struct rte_pci_device *dev, size_t private_data_size)
 static inline void
 rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev)
 {
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
-		eth_dev->device = NULL;
-		eth_dev->intr_handle = NULL;
-		rte_eth_dev_release_port_secondary(eth_dev);
-		return;
-	}
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 3a4dd4790..dfa122c1a 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -220,13 +220,6 @@ DPDK_18.08 {
 
 } DPDK_18.05;
 
-DPDK_18.11 {
-	global:
-
-	rte_eth_dev_release_port_secondary;
-
-} DPDK_18.08;
-
 EXPERIMENTAL {
 	global:
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v5 6/6] ethdev: complete closing of port
  2018-10-18  1:23 ` [dpdk-dev] [PATCH v5 0/6] " Thomas Monjalon
                     ` (4 preceding siblings ...)
  2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 5/6] ethdev: remove release function for secondary process Thomas Monjalon
@ 2018-10-18  1:24   ` Thomas Monjalon
  2018-10-18  8:33     ` Andrew Rybchenko
  5 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18  1:24 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

After closing a port, it cannot be restarted.
So there is no reason to not free all associated resources.

The last step was done with rte_eth_dev_detach() which is deprecated.
Instead of blindly removing the associated rte_device, the driver should
check if no more port (ethdev, cryptodev, etc) is open for the device.

The last ethdev freeing which were done by rte_eth_dev_detach(),
are now done at the end of rte_eth_dev_close().

Some drivers does not allocate MAC addresses dynamically or separately.
In those cases, the pointer is set to NULL, in order to avoid wrongly
freeing them in rte_eth_dev_release_port().

A closed port will have the state RTE_ETH_DEV_UNUSED which is
considered as invalid by rte_eth_dev_is_valid_port().
So validity is not checked anymore for closed ports in testpmd.

If the driver is trying to free the port again, the function
rte_eth_dev_release_port() will abort with -ENODEV error.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c                    | 16 +++-------------
 doc/guides/rel_notes/release_18_11.rst    |  4 ++++
 drivers/net/af_packet/rte_eth_af_packet.c |  4 +++-
 drivers/net/bnxt/bnxt_ethdev.c            |  4 ----
 drivers/net/failsafe/failsafe_ops.c       |  2 ++
 drivers/net/mlx4/mlx4.c                   |  2 ++
 drivers/net/mlx5/mlx5.c                   |  2 ++
 drivers/net/netvsc/hn_ethdev.c            |  5 ++++-
 drivers/net/pcap/rte_eth_pcap.c           |  5 +++++
 drivers/net/softnic/rte_eth_softnic.c     |  3 ++-
 drivers/net/tap/rte_eth_tap.c             |  3 +++
 drivers/net/vhost/rte_eth_vhost.c         |  4 ----
 lib/librte_ethdev/rte_ethdev.c            |  9 +++------
 lib/librte_ethdev/rte_ethdev.h            |  3 +--
 14 files changed, 34 insertions(+), 32 deletions(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 31aadec63..2bd3fd986 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1938,18 +1938,6 @@ port_is_started(portid_t port_id)
 	return 1;
 }
 
-static int
-port_is_closed(portid_t port_id)
-{
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return 0;
-
-	if (ports[port_id].port_status != RTE_PORT_CLOSED)
-		return 0;
-
-	return 1;
-}
-
 int
 start_port(portid_t pid)
 {
@@ -2252,6 +2240,8 @@ close_port(portid_t pid)
 			port_flow_flush(pi);
 		rte_eth_dev_close(pi);
 
+		remove_unused_fwd_ports();
+
 		if (rte_atomic16_cmpset(&(port->port_status),
 			RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0)
 			printf("Port %d cannot be set to closed\n", pi);
@@ -2342,7 +2332,7 @@ detach_port(portid_t port_id)
 
 	printf("Detaching a port...\n");
 
-	if (!port_is_closed(port_id)) {
+	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
 		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
 			printf("Port not stopped\n");
 			return;
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 2467d04e2..b982ca80e 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -215,6 +215,10 @@ API Changes
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
 
+* ethdev: A call to ``rte_eth_dev_release_port()`` has been added in
+  ``rte_eth_dev_close()``. As a consequence, a closed port is freed
+  and seen as invalid because of its state ``RTE_ETH_DEV_UNUSED``.
+
 * A new device flag, RTE_ETH_DEV_NOLIVE_MAC_ADDR, changes the order of
   actions inside rte_eth_dev_start regarding MAC set. Some NICs do not
   support MAC changes once the port has started and with this new device
diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 95a98c6b8..2678335f6 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -362,8 +362,10 @@ eth_stats_reset(struct rte_eth_dev *dev)
 }
 
 static void
-eth_dev_close(struct rte_eth_dev *dev __rte_unused)
+eth_dev_close(struct rte_eth_dev *dev)
 {
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 }
 
 static void
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 801c6ffad..141bd6376 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -712,10 +712,6 @@ static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 	if (bp->dev_stopped == 0)
 		bnxt_dev_stop_op(eth_dev);
 
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
 	if (bp->grp_info != NULL) {
 		rte_free(bp->grp_info);
 		bp->grp_info = NULL;
diff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c
index 7f8bcd4c6..f10433b30 100644
--- a/drivers/net/failsafe/failsafe_ops.c
+++ b/drivers/net/failsafe/failsafe_ops.c
@@ -331,6 +331,8 @@ fs_dev_close(struct rte_eth_dev *dev)
 		sdev->state = DEV_ACTIVE - 1;
 	}
 	fs_dev_free_queues(dev);
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	fs_unlock(dev, 0);
 }
 
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 7f07b8dc0..4a7b5e220 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -209,6 +209,8 @@ mlx4_dev_close(struct rte_eth_dev *dev)
 		mlx4_rx_queue_release(dev->data->rx_queues[i]);
 	for (i = 0; i != dev->data->nb_tx_queues; ++i)
 		mlx4_tx_queue_release(dev->data->tx_queues[i]);
+	/* mac_addrs must not be freed because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	mlx4_mr_release(dev);
 	if (priv->pd != NULL) {
 		assert(priv->ctx != NULL);
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index b2be74b51..82dd7ad41 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -337,6 +337,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 	}
 	memset(priv, 0, sizeof(*priv));
 	priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 }
 
 const struct eth_dev_ops mlx5_dev_ops = {
diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c
index aa38ee7a3..5a7463628 100644
--- a/drivers/net/netvsc/hn_ethdev.c
+++ b/drivers/net/netvsc/hn_ethdev.c
@@ -630,11 +630,14 @@ hn_dev_stop(struct rte_eth_dev *dev)
 }
 
 static void
-hn_dev_close(struct rte_eth_dev *dev __rte_unused)
+hn_dev_close(struct rte_eth_dev *dev)
 {
 	PMD_INIT_LOG(DEBUG, "close");
 
 	hn_vf_close(dev);
+
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 }
 
 static const struct eth_dev_ops hn_eth_dev_ops = {
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 7bbe72e25..bfc003663 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -623,6 +623,11 @@ eth_stats_reset(struct rte_eth_dev *dev)
 static void
 eth_dev_close(struct rte_eth_dev *dev __rte_unused)
 {
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	if (internals != NULL && internals->phy_mac == 0)
+		/* not dynamically allocated, must not be freed */
+		dev->data->mac_addrs = NULL;
 }
 
 static void
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 9a2418438..083519b38 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -194,8 +194,9 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 }
 
 static void
-pmd_dev_close(struct rte_eth_dev *dev __rte_unused)
+pmd_dev_close(struct rte_eth_dev *dev)
 {
+	dev->data->mac_addrs = NULL; /* statically allocated */
 	return;
 }
 
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 53d37b3cb..32f2f888d 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1000,6 +1000,9 @@ tap_dev_close(struct rte_eth_dev *dev)
 	 * Since TUN device has no more opened file descriptors
 	 * it will be removed from kernel
 	 */
+
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 }
 
 static void
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 0cd1a4642..d3e78503b 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -998,12 +998,8 @@ eth_dev_close(struct rte_eth_dev *dev)
 		for (i = 0; i < dev->data->nb_tx_queues; i++)
 			rte_free(dev->data->tx_queues[i]);
 
-	rte_free(dev->data->mac_addrs);
 	free(internal->dev_name);
 	free(internal->iface_name);
-	rte_free(internal);
-
-	dev->data->dev_private = NULL;
 }
 
 static int
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 178800a5b..987ba5ab1 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -367,6 +367,8 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 {
 	if (eth_dev == NULL)
 		return -EINVAL;
+	if (eth_dev->state == RTE_ETH_DEV_UNUSED)
+		return -ENODEV;
 
 	rte_eth_dev_shared_data_prepare();
 
@@ -1384,12 +1386,7 @@ rte_eth_dev_close(uint16_t port_id)
 	dev->data->dev_started = 0;
 	(*dev->dev_ops->dev_close)(dev);
 
-	dev->data->nb_rx_queues = 0;
-	rte_free(dev->data->rx_queues);
-	dev->data->rx_queues = NULL;
-	dev->data->nb_tx_queues = 0;
-	rte_free(dev->data->tx_queues);
-	dev->data->tx_queues = NULL;
+	rte_eth_dev_release_port(dev);
 }
 
 int
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index fb40c89e0..dcdeb184b 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1802,8 +1802,7 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
 
 /**
  * Close a stopped Ethernet device. The device cannot be restarted!
- * The function frees all resources except for needed by the
- * closed state. To free these resources, call rte_eth_dev_detach().
+ * The function frees all port resources.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/6] ethdev: fix doxygen comments of shared data fields
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 3/6] ethdev: fix doxygen comments of shared data fields Thomas Monjalon
@ 2018-10-18  7:11     ` Andrew Rybchenko
  0 siblings, 0 replies; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-18  7:11 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

On 10/18/18 4:23 AM, Thomas Monjalon wrote:
> Some doxygen comments were wrongly associated to the next field
> because of syntax /** instead of /**<
>
> Some other cleanups (like alignment) are done.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

Yesterday I made similar patch, but moving corresponding comments
before its structure members to make doxygen usage correct.
It looks also good when post-comments are indented as you do.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 4/6] ethdev: free all common data when releasing port
  2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 4/6] ethdev: free all common data when releasing port Thomas Monjalon
@ 2018-10-18  7:13     ` Andrew Rybchenko
  0 siblings, 0 replies; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-18  7:13 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

On 10/18/18 4:24 AM, Thomas Monjalon wrote:
> This is a clean-up of common ethdev data freeing.
> All data freeing are moved to rte_eth_dev_release_port()
> and done only in case of primary process.
>
> It is probably fixing some memory leaks for PMDs which were
> not freeing all data.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 5/6] ethdev: remove release function for secondary process
  2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 5/6] ethdev: remove release function for secondary process Thomas Monjalon
@ 2018-10-18  7:15     ` Andrew Rybchenko
  0 siblings, 0 replies; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-18  7:15 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

On 10/18/18 4:24 AM, Thomas Monjalon wrote:
> After previous changes, the function rte_eth_dev_release_port()
> can be used for primary or secondary process as well.
> The only difference with rte_eth_dev_release_port_secondary()
> is the shared lock used in rte_eth_dev_release_port().
>
> The function rte_eth_dev_release_port_secondary() was recently
> added in 18.11 cycle.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 2/6] app/testpmd: allow detaching a port not closed
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 2/6] app/testpmd: allow detaching a port not closed Thomas Monjalon
@ 2018-10-18  7:45     ` Andrew Rybchenko
  2018-10-18 10:51       ` Iremonger, Bernard
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-18  7:45 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

On 10/18/18 4:23 AM, Thomas Monjalon wrote:
> The testpmd application aim is for testing;
> so order of operations should not be enforced.
>
> There was a test to forbid detaching before closing a port.
> However, it may interesting to test what happens in such case.
> It is possible for a PMD to automatically close the port when detaching.

Yes. In the case of net/sfc it requires a patch to call sfc_dev_close()
from uninit. I think network PMD maintainers should be notified
to double-check drivers.

> in order to avoid a crash, it is checked that the port must be stopped
> before detaching (as for closing).

I thought that it is sufficient to stop traffic and the port may be stopped
automatically by PMD. Not sure about it, just would like to clarify my
previous notes.

> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

[...]

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 6/6] ethdev: complete closing of port
  2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 6/6] ethdev: complete closing of port Thomas Monjalon
@ 2018-10-18  8:33     ` Andrew Rybchenko
  2018-10-18  9:32       ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-18  8:33 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

On 10/18/18 4:24 AM, Thomas Monjalon wrote:
> After closing a port, it cannot be restarted.
> So there is no reason to not free all associated resources.
>
> The last step was done with rte_eth_dev_detach() which is deprecated.
> Instead of blindly removing the associated rte_device, the driver should
> check if no more port (ethdev, cryptodev, etc) is open for the device.
>
> The last ethdev freeing which were done by rte_eth_dev_detach(),
> are now done at the end of rte_eth_dev_close().
>
> Some drivers does not allocate MAC addresses dynamically or separately.
> In those cases, the pointer is set to NULL, in order to avoid wrongly
> freeing them in rte_eth_dev_release_port().
>
> A closed port will have the state RTE_ETH_DEV_UNUSED which is
> considered as invalid by rte_eth_dev_is_valid_port().
> So validity is not checked anymore for closed ports in testpmd.
>
> If the driver is trying to free the port again, the function
> rte_eth_dev_release_port() will abort with -ENODEV error.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

I've tested the patch series together with [1].

As I expected it makes problems and resource leaks if
rte_eth_dev_close() is used.

Everything is OK if I do port stop and detach (with net/sfc
patch which does close from uninit).

If I do port stop, close and detach, the last one returns
error since the device already released and net/sfc uninit
is never called.

Basically it should be one function which is called in both
cases: dev_close or pci_device remove. Similar changes
should be done in many PCI drivers.

If I drop the patch, everything seems to be work fine
from the first sight.
May be it should be removed from the patchset and
considered separately.

[1] http://patches.dpdk.org/project/dpdk/list/?series=1966

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 6/6] ethdev: complete closing of port
  2018-10-18  8:33     ` Andrew Rybchenko
@ 2018-10-18  9:32       ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18  9:32 UTC (permalink / raw)
  To: Andrew Rybchenko
  Cc: ferruh.yigit, dev, ophirmu, bernard.iremonger, rahul.lakkireddy

18/10/2018 10:33, Andrew Rybchenko:
> On 10/18/18 4:24 AM, Thomas Monjalon wrote:
> > After closing a port, it cannot be restarted.
> > So there is no reason to not free all associated resources.
> >
> > The last step was done with rte_eth_dev_detach() which is deprecated.
> > Instead of blindly removing the associated rte_device, the driver should
> > check if no more port (ethdev, cryptodev, etc) is open for the device.
> >
> > The last ethdev freeing which were done by rte_eth_dev_detach(),
> > are now done at the end of rte_eth_dev_close().
> >
> > Some drivers does not allocate MAC addresses dynamically or separately.
> > In those cases, the pointer is set to NULL, in order to avoid wrongly
> > freeing them in rte_eth_dev_release_port().
> >
> > A closed port will have the state RTE_ETH_DEV_UNUSED which is
> > considered as invalid by rte_eth_dev_is_valid_port().
> > So validity is not checked anymore for closed ports in testpmd.
> >
> > If the driver is trying to free the port again, the function
> > rte_eth_dev_release_port() will abort with -ENODEV error.
> >
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> 
> I've tested the patch series together with [1].

There are 2 use cases to consider:
	1/ rte_eth_dev_close + rte_dev_remove
	2/ rte_dev_remove without prior close

> As I expected it makes problems and resource leaks if
> rte_eth_dev_close() is used.
> 
> Everything is OK if I do port stop and detach (with net/sfc
> patch which does close from uninit).

This is the case #2.
It requires some PMD updates to avoid the leaks.
It was buggy in previous releases too, because it was not managing
devices with multiple ports.
I think we should continue recommending the use case #1 in 18.11,
and let time for PMDs to be fixed for use case #2.
It PMDs can be fixed in 18.11, it is even better.

> If I do port stop, close and detach, the last one returns
> error since the device already released and net/sfc uninit
> is never called.

This is the case #1.
The bug is assuming that the port is not freed when removing the device.
We should just skip closed ports without any error.
I can fix it in a v6.

> Basically it should be one function which is called in both
> cases: dev_close or pci_device remove. Similar changes
> should be done in many PCI drivers.

Yes, dev_close must be called for all non-closed ports of a PCI device
to remove.
Usually, PMDs have an implementation of dev_close which is different
of the uninit function called with rte_eth_dev_pci_generic_remove()
or rte_eth_dev_destroy(). They have no good reason to be different:
	typedef int (*ethdev_uninit_t)(struct rte_eth_dev *ethdev);
	typedef void (*eth_dev_close_t)(struct rte_eth_dev *dev);

> If I drop the patch, everything seems to be work fine
> from the first sight.
> May be it should be removed from the patchset and
> considered separately.

No, I think I should just fix the use case #1,
and let PMDs fixing the use case #2 when they have a chance.
In my opinion, the use case #2 was never advertised before,
so it is just opening the way for the support of this use case.

> [1] http://patches.dpdk.org/project/dpdk/list/?series=1966

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once
  2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once Thomas Monjalon
@ 2018-10-18 10:40     ` Iremonger, Bernard
  2018-10-18 11:29       ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Iremonger, Bernard @ 2018-10-18 10:40 UTC (permalink / raw)
  To: Thomas Monjalon, Yigit, Ferruh, arybchenko
  Cc: dev, ophirmu, rahul.lakkireddy, Wisam Jaddo

Hi Wisam,

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Thursday, October 18, 2018 2:24 AM
> To: Yigit, Ferruh <ferruh.yigit@intel.com>; arybchenko@solarflare.com
> Cc: dev@dpdk.org; ophirmu@mellanox.com; Iremonger, Bernard
> <bernard.iremonger@intel.com>; rahul.lakkireddy@chelsio.com; Wisam Jaddo
> <wisamm@mellanox.com>
> Subject: [PATCH v5 1/6] app/testpmd: fix ports list after removing several at
> once
> 
> From: Wisam Jaddo <wisamm@mellanox.com>
> 
> When detaching a port, the full rte_device is removed.
> If the rte_device was hosting several ports, the testpmd list of ports must be
> updated for multiple removals.

./devtools/check-git-log.sh -1
Missing 'Fixes' tag:
        app/testpmd: fix ports list after removing several at once
 
> Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
> ---
>  app/test-pmd/testpmd.c | 36 +++++++++++++++++++++++++-----------
>  1 file changed, 25 insertions(+), 11 deletions(-)
> 
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> 5dbbf783f..c4109417a 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -2186,6 +2186,30 @@ stop_port(portid_t pid)
>  	printf("Done\n");
>  }
> 
> +static void
> +remove_unused_fwd_ports(void)
> +{
> +	int i;
> +	int last_port_idx = nb_ports - 1;
> +
> +	for (i = 0; i < last_port_idx + 1; i++) { /* iterate in ports_ids */

Why not use  " i <= last_port_index" instead of adding back 1

> +		if (rte_eth_devices[ports_ids[i]].state ==
> RTE_ETH_DEV_UNUSED) {
> +			/* skip unused ports at the end */
> +			while (rte_eth_devices[ports_ids[last_port_idx]].state
> +					== RTE_ETH_DEV_UNUSED && i <=
> last_port_idx)

WARNING:LONG_LINE: line over 80 characters
#48: FILE: app/test-pmd/testpmd.c:2199:
+                                       == RTE_ETH_DEV_UNUSED && i <= last_port_idx)

> +				last_port_idx--;
> +			if (last_port_idx < i)
> +				break;
> +			/* overwrite unused port with last valid port */
> +			ports_ids[i] = ports_ids[last_port_idx];
> +			/* decrease ports count */
> +			last_port_idx--;
> +		}
> +	}
> +	nb_ports = rte_eth_dev_count_avail();
> +	update_fwd_ports(RTE_MAX_ETHPORTS);
> +}
> +
>  void
>  close_port(portid_t pid)
>  {
> @@ -2315,7 +2339,6 @@ void
>  detach_port(portid_t port_id)
>  {
>  	char name[RTE_ETH_NAME_MAX_LEN];
> -	uint16_t i;
> 
>  	printf("Detaching a port...\n");
> 
> @@ -2332,16 +2355,7 @@ detach_port(portid_t port_id)
>  		return;
>  	}
> 
> -	for (i = 0; i < nb_ports; i++) {
> -		if (ports_ids[i] == port_id) {
> -			ports_ids[i] = ports_ids[nb_ports-1];
> -			ports_ids[nb_ports-1] = 0;
> -			break;
> -		}
> -	}
> -	nb_ports = rte_eth_dev_count_avail();
> -
> -	update_fwd_ports(RTE_MAX_ETHPORTS);
> +	remove_unused_fwd_ports();
> 
>  	printf("Port %u is detached. Now total ports is %d\n",
>  			port_id, nb_ports);
> --
> 2.19.0

Regards,

Bernard.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 2/6] app/testpmd: allow detaching a port not closed
  2018-10-18  7:45     ` Andrew Rybchenko
@ 2018-10-18 10:51       ` Iremonger, Bernard
  2018-10-18 11:24         ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Iremonger, Bernard @ 2018-10-18 10:51 UTC (permalink / raw)
  To: Andrew Rybchenko, Thomas Monjalon, Yigit, Ferruh
  Cc: dev, ophirmu, rahul.lakkireddy

Hi Thomas,

> -----Original Message-----
> From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
> Sent: Thursday, October 18, 2018 8:45 AM
> To: Thomas Monjalon <thomas@monjalon.net>; Yigit, Ferruh
> <ferruh.yigit@intel.com>
> Cc: dev@dpdk.org; ophirmu@mellanox.com; Iremonger, Bernard
> <bernard.iremonger@intel.com>; rahul.lakkireddy@chelsio.com
> Subject: Re: [PATCH v5 2/6] app/testpmd: allow detaching a port not closed
> 
> On 10/18/18 4:23 AM, Thomas Monjalon wrote:
> > The testpmd application aim is for testing; so order of operations
> > should not be enforced.
> >
> > There was a test to forbid detaching before closing a port.
> > However, it may interesting to test what happens in such case.
> > It is possible for a PMD to automatically close the port when detaching.
> 
> Yes. In the case of net/sfc it requires a patch to call sfc_dev_close() from uninit.
> I think network PMD maintainers should be notified to double-check drivers.
> 
> > in order to avoid a crash, it is checked that the port must be stopped
> > before detaching (as for closing).
> 
> I thought that it is sufficient to stop traffic and the port may be stopped
> automatically by PMD. Not sure about it, just would like to clarify my previous
> notes.
> 
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> 
> [...]

This patch seems too  risky as it may impact some of the PMD's.

Regards,

Bernard.


^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 2/6] app/testpmd: allow detaching a port not closed
  2018-10-18 10:51       ` Iremonger, Bernard
@ 2018-10-18 11:24         ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18 11:24 UTC (permalink / raw)
  To: Iremonger, Bernard
  Cc: dev, Andrew Rybchenko, Yigit, Ferruh, ophirmu, rahul.lakkireddy

18/10/2018 12:51, Iremonger, Bernard:
> From: Andrew Rybchenko [mailto:arybchenko@solarflare.com]
> > On 10/18/18 4:23 AM, Thomas Monjalon wrote:
> > > The testpmd application aim is for testing; so order of operations
> > > should not be enforced.
> > >
> > > There was a test to forbid detaching before closing a port.
> > > However, it may interesting to test what happens in such case.
> > > It is possible for a PMD to automatically close the port when detaching.
> > 
> > Yes. In the case of net/sfc it requires a patch to call sfc_dev_close() from uninit.
> > I think network PMD maintainers should be notified to double-check drivers.
> > 
> > > in order to avoid a crash, it is checked that the port must be stopped
> > > before detaching (as for closing).
> > 
> > I thought that it is sufficient to stop traffic and the port may be stopped
> > automatically by PMD. Not sure about it, just would like to clarify my previous
> > notes.
> > 
> > > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> > 
> > [...]
> 
> This patch seems too  risky as it may impact some of the PMD's.

Yes, it will not work for all PMDs.
If we want to allow this scenario, we'll need to improve some PMDs.
This patch is just allowing to test the scenario.
It will help PMD developers, so I think it is more helpful than risky.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once
  2018-10-18 10:40     ` Iremonger, Bernard
@ 2018-10-18 11:29       ` Thomas Monjalon
  2018-10-18 11:41         ` Iremonger, Bernard
  2018-10-18 11:49         ` Wisam Monther
  0 siblings, 2 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18 11:29 UTC (permalink / raw)
  To: Iremonger, Bernard
  Cc: dev, Yigit, Ferruh, arybchenko, ophirmu, rahul.lakkireddy, Wisam Jaddo

18/10/2018 12:40, Iremonger, Bernard:
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > 
> > From: Wisam Jaddo <wisamm@mellanox.com>
> > 
> > When detaching a port, the full rte_device is removed.
> > If the rte_device was hosting several ports, the testpmd list of ports must be
> > updated for multiple removals.
> 
> ./devtools/check-git-log.sh -1
> Missing 'Fixes' tag:
>         app/testpmd: fix ports list after removing several at once

I think it is OK.
It is fixing a case which was not tested before.
And we don't really need to backport it.

> > Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
> > ---
> >  app/test-pmd/testpmd.c | 36 +++++++++++++++++++++++++-----------
> >  1 file changed, 25 insertions(+), 11 deletions(-)
> > 
> > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> > 5dbbf783f..c4109417a 100644
> > --- a/app/test-pmd/testpmd.c
> > +++ b/app/test-pmd/testpmd.c
> > @@ -2186,6 +2186,30 @@ stop_port(portid_t pid)
> >  	printf("Done\n");
> >  }
> > 
> > +static void
> > +remove_unused_fwd_ports(void)
> > +{
> > +	int i;
> > +	int last_port_idx = nb_ports - 1;
> > +
> > +	for (i = 0; i < last_port_idx + 1; i++) { /* iterate in ports_ids */
> 
> Why not use  " i <= last_port_index" instead of adding back 1

If Wisam agrees, I can fix it in v6.

> > +		if (rte_eth_devices[ports_ids[i]].state ==
> > RTE_ETH_DEV_UNUSED) {
> > +			/* skip unused ports at the end */
> > +			while (rte_eth_devices[ports_ids[last_port_idx]].state
> > +					== RTE_ETH_DEV_UNUSED && i <=
> > last_port_idx)
> 
> WARNING:LONG_LINE: line over 80 characters
> #48: FILE: app/test-pmd/testpmd.c:2199:
> +                                       == RTE_ETH_DEV_UNUSED && i <= last_port_idx)

Will fix it.
Anyway, we should reverse the order of this check in order to avoid
accessing ports_ids[-1].

> > +				last_port_idx--;

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once
  2018-10-18 11:29       ` Thomas Monjalon
@ 2018-10-18 11:41         ` Iremonger, Bernard
  2018-10-18 14:21           ` Thomas Monjalon
  2018-10-18 11:49         ` Wisam Monther
  1 sibling, 1 reply; 78+ messages in thread
From: Iremonger, Bernard @ 2018-10-18 11:41 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, Yigit, Ferruh, arybchenko, ophirmu, rahul.lakkireddy, Wisam Jaddo

Hi Thomas

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Thursday, October 18, 2018 12:29 PM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>
> Cc: dev@dpdk.org; Yigit, Ferruh <ferruh.yigit@intel.com>;
> arybchenko@solarflare.com; ophirmu@mellanox.com;
> rahul.lakkireddy@chelsio.com; Wisam Jaddo <wisamm@mellanox.com>
> Subject: Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after
> removing several at once
> 
> 18/10/2018 12:40, Iremonger, Bernard:
> > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > >
> > > From: Wisam Jaddo <wisamm@mellanox.com>
> > >
> > > When detaching a port, the full rte_device is removed.
> > > If the rte_device was hosting several ports, the testpmd list of
> > > ports must be updated for multiple removals.
> >
> > ./devtools/check-git-log.sh -1
> > Missing 'Fixes' tag:
> >         app/testpmd: fix ports list after removing several at once
> 
> I think it is OK.
> It is fixing a case which was not tested before.
> And we don't really need to backport it.

If "fix" is removed from the commit message then the fixes line will not be needed.
However if it is a real fix, then I think fixes line should be added .

> 
> > > Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>

<snip>

Regards,

Bernard.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once
  2018-10-18 11:29       ` Thomas Monjalon
  2018-10-18 11:41         ` Iremonger, Bernard
@ 2018-10-18 11:49         ` Wisam Monther
  2018-10-18 13:22           ` Iremonger, Bernard
  1 sibling, 1 reply; 78+ messages in thread
From: Wisam Monther @ 2018-10-18 11:49 UTC (permalink / raw)
  To: Thomas Monjalon, Iremonger, Bernard
  Cc: dev, Yigit, Ferruh, arybchenko, Ophir Munk, rahul.lakkireddy

Are we saving cycles by set it to be <= instead of < _ +1?

BRs,
Wisam Jaddo

From: Thomas Monjalon<mailto:thomas@monjalon.net>
Sent: Thursday, October 18, 2018 2:29 PM
To: Iremonger, Bernard<mailto:bernard.iremonger@intel.com>
Cc: dev@dpdk.org<mailto:dev@dpdk.org>; Yigit, Ferruh<mailto:ferruh.yigit@intel.com>; arybchenko@solarflare.com<mailto:arybchenko@solarflare.com>; Ophir Munk<mailto:ophirmu@mellanox.com>; rahul.lakkireddy@chelsio.com<mailto:rahul.lakkireddy@chelsio.com>; Wisam Monther<mailto:wisamm@mellanox.com>
Subject: Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once

18/10/2018 12:40, Iremonger, Bernard:
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> >
> > From: Wisam Jaddo <wisamm@mellanox.com>
> >
> > When detaching a port, the full rte_device is removed.
> > If the rte_device was hosting several ports, the testpmd list of ports must be
> > updated for multiple removals.
>
> ./devtools/check-git-log.sh -1
> Missing 'Fixes' tag:
>         app/testpmd: fix ports list after removing several at once

I think it is OK.
It is fixing a case which was not tested before.
And we don't really need to backport it.

> > Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
> > ---
> >  app/test-pmd/testpmd.c | 36 +++++++++++++++++++++++++-----------
> >  1 file changed, 25 insertions(+), 11 deletions(-)
> >
> > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> > 5dbbf783f..c4109417a 100644
> > --- a/app/test-pmd/testpmd.c
> > +++ b/app/test-pmd/testpmd.c
> > @@ -2186,6 +2186,30 @@ stop_port(portid_t pid)
> >      printf("Done\n");
> >  }
> >
> > +static void
> > +remove_unused_fwd_ports(void)
> > +{
> > +   int i;
> > +   int last_port_idx = nb_ports - 1;
> > +
> > +   for (i = 0; i < last_port_idx + 1; i++) { /* iterate in ports_ids */
>
> Why not use  " i <= last_port_index" instead of adding back 1

If Wisam agrees, I can fix it in v6.

> > +           if (rte_eth_devices[ports_ids[i]].state ==
> > RTE_ETH_DEV_UNUSED) {
> > +                   /* skip unused ports at the end */
> > +                   while (rte_eth_devices[ports_ids[last_port_idx]].state
> > +                                   == RTE_ETH_DEV_UNUSED && i <=
> > last_port_idx)
>
> WARNING:LONG_LINE: line over 80 characters
> #48: FILE: app/test-pmd/testpmd.c:2199:
> +                                       == RTE_ETH_DEV_UNUSED && i <= last_port_idx)

Will fix it.
Anyway, we should reverse the order of this check in order to avoid
accessing ports_ids[-1].

> > +                           last_port_idx--;

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once
  2018-10-18 11:49         ` Wisam Monther
@ 2018-10-18 13:22           ` Iremonger, Bernard
  0 siblings, 0 replies; 78+ messages in thread
From: Iremonger, Bernard @ 2018-10-18 13:22 UTC (permalink / raw)
  To: Wisam Monther, Thomas Monjalon
  Cc: dev, Yigit, Ferruh, arybchenko, Ophir Munk, rahul.lakkireddy

Hi Wisam,

From: Wisam Monther [mailto:wisamm@mellanox.com]
Sent: Thursday, October 18, 2018 12:49 PM
To: Thomas Monjalon <thomas@monjalon.net>; Iremonger, Bernard <bernard.iremonger@intel.com>
Cc: dev@dpdk.org; Yigit, Ferruh <ferruh.yigit@intel.com>; arybchenko@solarflare.com; Ophir Munk <ophirmu@mellanox.com>; rahul.lakkireddy@chelsio.com
Subject: RE: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once

Are we saving cycles by set it to be <= instead of < _ +1?

No idea, just looks cleaner to me.

BRs,
Wisam Jaddo
<snip>

Regards,

Bernard.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once
  2018-10-18 11:41         ` Iremonger, Bernard
@ 2018-10-18 14:21           ` Thomas Monjalon
  2018-10-18 16:42             ` Iremonger, Bernard
  0 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18 14:21 UTC (permalink / raw)
  To: Iremonger, Bernard
  Cc: dev, Yigit, Ferruh, arybchenko, ophirmu, rahul.lakkireddy, Wisam Jaddo

18/10/2018 13:41, Iremonger, Bernard:
> Hi Thomas
> 
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > 18/10/2018 12:40, Iremonger, Bernard:
> > > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > >
> > > > From: Wisam Jaddo <wisamm@mellanox.com>
> > > >
> > > > When detaching a port, the full rte_device is removed.
> > > > If the rte_device was hosting several ports, the testpmd list of
> > > > ports must be updated for multiple removals.
> > >
> > > ./devtools/check-git-log.sh -1
> > > Missing 'Fixes' tag:
> > >         app/testpmd: fix ports list after removing several at once
> > 
> > I think it is OK.
> > It is fixing a case which was not tested before.
> > And we don't really need to backport it.
> 
> If "fix" is removed from the commit message then the fixes line will not be needed.
> However if it is a real fix, then I think fixes line should be added .

I know, I am the one implementing this check :-)
If I add a Fixes: line, it will warn about a lack of Cc:stable.
But we don't need to backport this.
That's why I think we can ignore this warning.

Reminder: it is just warning, not a mandatory requirement.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once
  2018-10-18 14:21           ` Thomas Monjalon
@ 2018-10-18 16:42             ` Iremonger, Bernard
  2018-10-18 17:06               ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Iremonger, Bernard @ 2018-10-18 16:42 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, Yigit, Ferruh, arybchenko, ophirmu, rahul.lakkireddy, Wisam Jaddo

Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Thursday, October 18, 2018 3:21 PM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>
> Cc: dev@dpdk.org; Yigit, Ferruh <ferruh.yigit@intel.com>;
> arybchenko@solarflare.com; ophirmu@mellanox.com;
> rahul.lakkireddy@chelsio.com; Wisam Jaddo <wisamm@mellanox.com>
> Subject: Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after
> removing several at once
> 
> 18/10/2018 13:41, Iremonger, Bernard:
> > Hi Thomas
> >
> > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > 18/10/2018 12:40, Iremonger, Bernard:
> > > > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > > >
> > > > > From: Wisam Jaddo <wisamm@mellanox.com>
> > > > >
> > > > > When detaching a port, the full rte_device is removed.
> > > > > If the rte_device was hosting several ports, the testpmd list of
> > > > > ports must be updated for multiple removals.
> > > >
> > > > ./devtools/check-git-log.sh -1
> > > > Missing 'Fixes' tag:
> > > >         app/testpmd: fix ports list after removing several at once
> > >
> > > I think it is OK.
> > > It is fixing a case which was not tested before.
> > > And we don't really need to backport it.
> >
> > If "fix" is removed from the commit message then the fixes line will not be
> needed.
> > However if it is a real fix, then I think fixes line should be added .
> 
> I know, I am the one implementing this check :-) If I add a Fixes: line, it will warn
> about a lack of Cc:stable.
> But we don't need to backport this.
> That's why I think we can ignore this warning.
> 
> Reminder: it is just warning, not a mandatory requirement.
> 
> 
As this does not seem to be a normal "fix", how about replacing "fix" with something like "update", then there will be no warning to ignore.
Better not have warnings.

Regards,

Bernard.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once
  2018-10-18 16:42             ` Iremonger, Bernard
@ 2018-10-18 17:06               ` Thomas Monjalon
  0 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-18 17:06 UTC (permalink / raw)
  To: Iremonger, Bernard
  Cc: dev, Yigit, Ferruh, arybchenko, ophirmu, rahul.lakkireddy, Wisam Jaddo

18/10/2018 18:42, Iremonger, Bernard:
> Hi Thomas,
> 
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > 18/10/2018 13:41, Iremonger, Bernard:
> > > Hi Thomas
> > >
> > > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > > 18/10/2018 12:40, Iremonger, Bernard:
> > > > > From: Thomas Monjalon [mailto:thomas@monjalon.net]
> > > > > >
> > > > > > From: Wisam Jaddo <wisamm@mellanox.com>
> > > > > >
> > > > > > When detaching a port, the full rte_device is removed.
> > > > > > If the rte_device was hosting several ports, the testpmd list of
> > > > > > ports must be updated for multiple removals.
> > > > >
> > > > > ./devtools/check-git-log.sh -1
> > > > > Missing 'Fixes' tag:
> > > > >         app/testpmd: fix ports list after removing several at once
> > > >
> > > > I think it is OK.
> > > > It is fixing a case which was not tested before.
> > > > And we don't really need to backport it.
> > >
> > > If "fix" is removed from the commit message then the fixes line will not be
> > needed.
> > > However if it is a real fix, then I think fixes line should be added .
> > 
> > I know, I am the one implementing this check :-) If I add a Fixes: line, it will warn
> > about a lack of Cc:stable.
> > But we don't need to backport this.
> > That's why I think we can ignore this warning.
> > 
> > Reminder: it is just warning, not a mandatory requirement.
> > 
> > 
> As this does not seem to be a normal "fix", how about replacing "fix" with something like "update", then there will be no warning to ignore.
> Better not have warnings.

Yes, I thought about it and felt that "update" would not have the same meaning.
If nobody has a better idea, I will replace with "update" instead of "fix".

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v6 0/6] ethdev port freeing
  2018-09-07 23:39 [dpdk-dev] [RFC] ethdev: complete closing to free all resources Thomas Monjalon
                   ` (5 preceding siblings ...)
  2018-10-18  1:23 ` [dpdk-dev] [PATCH v5 0/6] " Thomas Monjalon
@ 2018-10-19  2:07 ` Thomas Monjalon
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 1/6] app/testpmd: update port list for multiple removals Thomas Monjalon
                     ` (6 more replies)
  6 siblings, 7 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-19  2:07 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

The function rte_eth_dev_detach() is freeing a port and its underlying
rte_device object. The issue is that we may have several ports
associated to the same rte_device.

The right replacement is to free the port, and free the rte_device
if no more ports.
At ethdev level, the public function for port freeing is rte_eth_dev_close().
The only miss is rte_eth_dev_release_port() to free all port resources.

This patchset does a cleanup by moving as much ethdev data freeing
as possible in an unique function rte_eth_dev_release_port(),
and call this function in rte_eth_dev_close().
The port is released on close only if the driver supports it.


Changes in v6:
  - fix testpmd ports list iteration
  - keep old behaviour
  - add flag RTE_ETH_DEV_CLOSE_REMOVE to enable new behaviour (port release)

Changes in v5:
  - fix testpmd for detaching multi-ports device
  - fix testpmd for detaching only stopped ports
  - add a release note about closed port freeing and state
  - fix some doxygen comments in rte_eth_dev_data
  - improve doxygen of rte_eth_dev_release_port()
  - fix data freeing in some drivers

Changes in v4:
  - do not free data fields which are not dynamically allocated blocks
  - remove rte_eth_dev_release_port_secondary()
  - remove testpmd check to detach without closing

Changes in v3:
  - free queues, MAC addresses and private structure
    in rte_eth_dev_release_port.


Thomas Monjalon (5):
  app/testpmd: allow detaching a port not closed
  ethdev: fix doxygen comments of shared data fields
  ethdev: free all common data when releasing port
  ethdev: remove release function for secondary process
  ethdev: complete closing of port

Wisam Jaddo (1):
  app/testpmd: update port list for multiple removals

 app/test-pmd/testpmd.c                    | 65 +++++++++++++----------
 doc/guides/rel_notes/release_18_11.rst    |  5 ++
 drivers/net/af_packet/rte_eth_af_packet.c |  7 +--
 drivers/net/ark/ark_ethdev.c              |  1 -
 drivers/net/avf/avf_ethdev.c              |  3 --
 drivers/net/avp/avp_ethdev.c              |  5 --
 drivers/net/axgbe/axgbe_ethdev.c          |  3 --
 drivers/net/bnxt/bnxt_ethdev.c            |  4 --
 drivers/net/bonding/rte_eth_bond_pmd.c    | 11 ++--
 drivers/net/cxgbe/cxgbe_main.c            | 16 +-----
 drivers/net/cxgbe/cxgbevf_main.c          |  9 +---
 drivers/net/dpaa/dpaa_ethdev.c            | 10 ----
 drivers/net/dpaa2/dpaa2_ethdev.c          | 10 ----
 drivers/net/e1000/em_ethdev.c             |  3 --
 drivers/net/e1000/igb_ethdev.c            |  6 ---
 drivers/net/enetc/enetc_ethdev.c          |  4 +-
 drivers/net/failsafe/failsafe.c           |  6 ++-
 drivers/net/fm10k/fm10k_ethdev.c          |  8 ---
 drivers/net/i40e/i40e_ethdev.c            |  3 --
 drivers/net/i40e/i40e_ethdev_vf.c         |  3 --
 drivers/net/i40e/i40e_vf_representor.c    |  5 +-
 drivers/net/ixgbe/ixgbe_ethdev.c          |  9 ----
 drivers/net/ixgbe/ixgbe_vf_representor.c  |  5 +-
 drivers/net/kni/rte_eth_kni.c             |  7 +--
 drivers/net/liquidio/lio_ethdev.c         |  3 --
 drivers/net/mlx4/mlx4.c                   |  7 ++-
 drivers/net/mlx5/mlx5.c                   | 11 ++--
 drivers/net/mvneta/mvneta_ethdev.c        | 16 ++----
 drivers/net/mvpp2/mrvl_ethdev.c           | 16 ++----
 drivers/net/netvsc/hn_ethdev.c            | 15 +-----
 drivers/net/null/rte_eth_null.c           |  7 ++-
 drivers/net/octeontx/octeontx_ethdev.c    | 31 +++++------
 drivers/net/pcap/rte_eth_pcap.c           | 14 +++--
 drivers/net/qede/qede_ethdev.c            |  5 --
 drivers/net/ring/rte_eth_ring.c           |  6 +--
 drivers/net/sfc/sfc_ethdev.c              |  3 --
 drivers/net/softnic/rte_eth_softnic.c     |  7 ++-
 drivers/net/szedata2/rte_eth_szedata2.c   |  1 -
 drivers/net/tap/rte_eth_tap.c             |  8 ++-
 drivers/net/vhost/rte_eth_vhost.c         | 11 ++--
 drivers/net/virtio/virtio_ethdev.c        |  3 --
 drivers/net/virtio/virtio_user_ethdev.c   |  3 --
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  3 --
 lib/librte_ethdev/rte_ethdev.c            | 46 +++++++---------
 lib/librte_ethdev/rte_ethdev.h            |  9 +++-
 lib/librte_ethdev/rte_ethdev_core.h       | 38 +++++++------
 lib/librte_ethdev/rte_ethdev_driver.h     | 23 +++-----
 lib/librte_ethdev/rte_ethdev_pci.h        | 17 ------
 lib/librte_ethdev/rte_ethdev_version.map  |  7 ---
 49 files changed, 188 insertions(+), 330 deletions(-)

-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v6 1/6] app/testpmd: update port list for multiple removals
  2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
@ 2018-10-19  2:07   ` Thomas Monjalon
  2018-10-19 14:32     ` Iremonger, Bernard
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 2/6] app/testpmd: allow detaching a port not closed Thomas Monjalon
                     ` (5 subsequent siblings)
  6 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-19  2:07 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy, Wisam Jaddo

From: Wisam Jaddo <wisamm@mellanox.com>

When detaching a port, the full rte_device is removed.
If the rte_device was hosting several ports,
the testpmd list of ports must be updated for multiple removals.

Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
---
 app/test-pmd/testpmd.c | 37 ++++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 5dbbf783f..2c0b4a021 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2186,6 +2186,31 @@ stop_port(portid_t pid)
 	printf("Done\n");
 }
 
+static void
+remove_unused_fwd_ports(void)
+{
+	int i;
+	int last_port_idx = nb_ports - 1;
+
+	for (i = 0; i <= last_port_idx; i++) { /* iterate in ports_ids */
+		if (rte_eth_devices[ports_ids[i]].state != RTE_ETH_DEV_UNUSED)
+			continue;
+		/* skip unused ports at the end */
+		while (i <= last_port_idx &&
+				rte_eth_devices[ports_ids[last_port_idx]].state
+				== RTE_ETH_DEV_UNUSED)
+			last_port_idx--;
+		if (last_port_idx < i)
+			break;
+		/* overwrite unused port with last valid port */
+		ports_ids[i] = ports_ids[last_port_idx];
+		/* decrease ports count */
+		last_port_idx--;
+	}
+	nb_ports = rte_eth_dev_count_avail();
+	update_fwd_ports(RTE_MAX_ETHPORTS);
+}
+
 void
 close_port(portid_t pid)
 {
@@ -2315,7 +2340,6 @@ void
 detach_port(portid_t port_id)
 {
 	char name[RTE_ETH_NAME_MAX_LEN];
-	uint16_t i;
 
 	printf("Detaching a port...\n");
 
@@ -2332,16 +2356,7 @@ detach_port(portid_t port_id)
 		return;
 	}
 
-	for (i = 0; i < nb_ports; i++) {
-		if (ports_ids[i] == port_id) {
-			ports_ids[i] = ports_ids[nb_ports-1];
-			ports_ids[nb_ports-1] = 0;
-			break;
-		}
-	}
-	nb_ports = rte_eth_dev_count_avail();
-
-	update_fwd_ports(RTE_MAX_ETHPORTS);
+	remove_unused_fwd_ports();
 
 	printf("Port %u is detached. Now total ports is %d\n",
 			port_id, nb_ports);
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v6 2/6] app/testpmd: allow detaching a port not closed
  2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 1/6] app/testpmd: update port list for multiple removals Thomas Monjalon
@ 2018-10-19  2:07   ` Thomas Monjalon
  2018-10-19 14:32     ` Iremonger, Bernard
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 3/6] ethdev: fix doxygen comments of shared data fields Thomas Monjalon
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-19  2:07 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

The testpmd application aim is for testing;
so order of operations should not be enforced.

There was a test to forbid detaching before closing a port.
However, it may interesting to test what happens in such case.
It is possible for a PMD to automatically close the port when detaching.

in order to avoid a crash, it is checked that the port must be stopped
before detaching (as for closing).

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 2c0b4a021..d5a8a14af 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2344,13 +2344,15 @@ detach_port(portid_t port_id)
 	printf("Detaching a port...\n");
 
 	if (!port_is_closed(port_id)) {
-		printf("Please close port first\n");
-		return;
+		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
+			printf("Port not stopped\n");
+			return;
+		}
+		printf("Port was not closed\n");
+		if (ports[port_id].flow_list)
+			port_flow_flush(port_id);
 	}
 
-	if (ports[port_id].flow_list)
-		port_flow_flush(port_id);
-
 	if (rte_eth_dev_detach(port_id, name)) {
 		TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
 		return;
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v6 3/6] ethdev: fix doxygen comments of shared data fields
  2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 1/6] app/testpmd: update port list for multiple removals Thomas Monjalon
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 2/6] app/testpmd: allow detaching a port not closed Thomas Monjalon
@ 2018-10-19  2:07   ` Thomas Monjalon
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 4/6] ethdev: free all common data when releasing port Thomas Monjalon
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-19  2:07 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

Some doxygen comments were wrongly associated to the next field
because of syntax /** instead of /**<

Some other cleanups (like alignment) are done.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_ethdev/rte_ethdev_core.h | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 33d12b3a2..03ec4992a 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -581,22 +581,20 @@ struct rte_eth_dev_data {
 
 	void *dev_private;              /**< PMD-specific private data */
 
-	struct rte_eth_link dev_link;
-	/**< Link-level information & status */
-
+	struct rte_eth_link dev_link;   /**< Link-level information & status. */
 	struct rte_eth_conf dev_conf;   /**< Configuration applied to device. */
 	uint16_t mtu;                   /**< Maximum Transmission Unit. */
-
 	uint32_t min_rx_buf_size;
-	/**< Common rx buffer size handled by all queues */
+			/**< Common RX buffer size handled by all queues. */
 
 	uint64_t rx_mbuf_alloc_failed; /**< RX ring mbuf allocation failures. */
-	struct ether_addr* mac_addrs;/**< Device Ethernet Link address. */
+	struct ether_addr *mac_addrs;  /**< Device Ethernet link address. */
 	uint64_t mac_pool_sel[ETH_NUM_RECEIVE_MAC_ADDR];
-	/** bitmap array of associating Ethernet MAC addresses to pools */
-	struct ether_addr* hash_mac_addrs;
-	/** Device Ethernet MAC addresses of hash filtering. */
+			/**< Bitmap associating MAC addresses to pools. */
+	struct ether_addr *hash_mac_addrs;
+			/**< Device Ethernet MAC addresses of hash filtering. */
 	uint16_t port_id;           /**< Device [external] port identifier. */
+
 	__extension__
 	uint8_t promiscuous   : 1, /**< RX promiscuous mode ON(1) / OFF(0). */
 		scattered_rx : 1,  /**< RX of scattered packets is ON(1) / OFF(0) */
@@ -604,14 +602,14 @@ struct rte_eth_dev_data {
 		dev_started : 1,   /**< Device state: STARTED(1) / STOPPED(0). */
 		lro         : 1;   /**< RX LRO is ON(1) / OFF(0) */
 	uint8_t rx_queue_state[RTE_MAX_QUEUES_PER_PORT];
-	/** Queues state: STARTED(1) / STOPPED(0) */
+			/**< Queues state: STARTED(1) / STOPPED(0). */
 	uint8_t tx_queue_state[RTE_MAX_QUEUES_PER_PORT];
-	/** Queues state: STARTED(1) / STOPPED(0) */
-	uint32_t dev_flags; /**< Capabilities */
-	enum rte_kernel_driver kdrv;    /**< Kernel driver passthrough */
-	int numa_node;  /**< NUMA node connection */
+			/**< Queues state: STARTED(1) / STOPPED(0). */
+	uint32_t dev_flags;             /**< Capabilities. */
+	enum rte_kernel_driver kdrv;    /**< Kernel driver passthrough. */
+	int numa_node;                  /**< NUMA node connection. */
 	struct rte_vlan_filter_conf vlan_filter_conf;
-	/**< VLAN filter configuration. */
+			/**< VLAN filter configuration. */
 	struct rte_eth_dev_owner owner; /**< The port owner. */
 } __rte_cache_aligned;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v6 4/6] ethdev: free all common data when releasing port
  2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
                     ` (2 preceding siblings ...)
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 3/6] ethdev: fix doxygen comments of shared data fields Thomas Monjalon
@ 2018-10-19  2:07   ` Thomas Monjalon
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 5/6] ethdev: remove release function for secondary process Thomas Monjalon
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-19  2:07 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

This is a clean-up of common ethdev data freeing.
All data freeing are moved to rte_eth_dev_release_port()
and done only in case of primary process.

It is probably fixing some memory leaks for PMDs which were
not freeing all data.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/net/af_packet/rte_eth_af_packet.c |  5 ++--
 drivers/net/ark/ark_ethdev.c              |  1 -
 drivers/net/avf/avf_ethdev.c              |  3 ---
 drivers/net/avp/avp_ethdev.c              |  5 ----
 drivers/net/axgbe/axgbe_ethdev.c          |  3 ---
 drivers/net/bnxt/bnxt_ethdev.c            |  4 ----
 drivers/net/bonding/rte_eth_bond_pmd.c    |  9 +++----
 drivers/net/cxgbe/cxgbe_main.c            | 16 ++-----------
 drivers/net/cxgbe/cxgbevf_main.c          |  9 +------
 drivers/net/dpaa/dpaa_ethdev.c            | 10 --------
 drivers/net/dpaa2/dpaa2_ethdev.c          | 10 --------
 drivers/net/e1000/em_ethdev.c             |  3 ---
 drivers/net/e1000/igb_ethdev.c            |  6 -----
 drivers/net/enetc/enetc_ethdev.c          |  4 +---
 drivers/net/failsafe/failsafe.c           |  6 +++--
 drivers/net/fm10k/fm10k_ethdev.c          |  8 -------
 drivers/net/i40e/i40e_ethdev.c            |  3 ---
 drivers/net/i40e/i40e_ethdev_vf.c         |  3 ---
 drivers/net/i40e/i40e_vf_representor.c    |  5 +++-
 drivers/net/ixgbe/ixgbe_ethdev.c          |  9 -------
 drivers/net/ixgbe/ixgbe_vf_representor.c  |  5 +++-
 drivers/net/kni/rte_eth_kni.c             |  5 ++--
 drivers/net/liquidio/lio_ethdev.c         |  3 ---
 drivers/net/mlx4/mlx4.c                   |  7 +++++-
 drivers/net/mlx5/mlx5.c                   | 11 ++++++---
 drivers/net/mvneta/mvneta_ethdev.c        | 16 ++++---------
 drivers/net/mvpp2/mrvl_ethdev.c           | 16 ++++---------
 drivers/net/netvsc/hn_ethdev.c            | 15 ++----------
 drivers/net/null/rte_eth_null.c           |  4 ++--
 drivers/net/octeontx/octeontx_ethdev.c    | 29 +++++++++--------------
 drivers/net/pcap/rte_eth_pcap.c           |  8 +++----
 drivers/net/qede/qede_ethdev.c            |  5 ----
 drivers/net/ring/rte_eth_ring.c           |  6 ++---
 drivers/net/sfc/sfc_ethdev.c              |  3 ---
 drivers/net/softnic/rte_eth_softnic.c     |  7 +++---
 drivers/net/szedata2/rte_eth_szedata2.c   |  1 -
 drivers/net/tap/rte_eth_tap.c             |  6 ++++-
 drivers/net/vhost/rte_eth_vhost.c         |  9 +++----
 drivers/net/virtio/virtio_ethdev.c        |  3 ---
 drivers/net/virtio/virtio_user_ethdev.c   |  3 ---
 drivers/net/vmxnet3/vmxnet3_ethdev.c      |  3 ---
 lib/librte_ethdev/rte_ethdev.c            | 21 ++++++++--------
 lib/librte_ethdev/rte_ethdev_core.h       | 14 ++++++++---
 lib/librte_ethdev/rte_ethdev_driver.h     |  9 ++++++-
 lib/librte_ethdev/rte_ethdev_pci.h        | 10 --------
 45 files changed, 109 insertions(+), 232 deletions(-)

diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 376d76302..2efc17725 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -986,6 +986,9 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
@@ -996,8 +999,6 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	}
 	free(internals->if_name);
 
-	rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/ark/ark_ethdev.c b/drivers/net/ark/ark_ethdev.c
index 552ca01a6..70d62ec7f 100644
--- a/drivers/net/ark/ark_ethdev.c
+++ b/drivers/net/ark/ark_ethdev.c
@@ -506,7 +506,6 @@ eth_ark_dev_uninit(struct rte_eth_dev *dev)
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
-	rte_free(dev->data->mac_addrs);
 	return 0;
 }
 
diff --git a/drivers/net/avf/avf_ethdev.c b/drivers/net/avf/avf_ethdev.c
index e56d57c43..13eec1b45 100644
--- a/drivers/net/avf/avf_ethdev.c
+++ b/drivers/net/avf/avf_ethdev.c
@@ -1303,9 +1303,6 @@ avf_dev_uninit(struct rte_eth_dev *dev)
 	rte_free(vf->aq_resp);
 	vf->aq_resp = NULL;
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	if (vf->rss_lut) {
 		rte_free(vf->rss_lut);
 		vf->rss_lut = NULL;
diff --git a/drivers/net/avp/avp_ethdev.c b/drivers/net/avp/avp_ethdev.c
index 0f8ccb954..09388d05f 100644
--- a/drivers/net/avp/avp_ethdev.c
+++ b/drivers/net/avp/avp_ethdev.c
@@ -1036,11 +1036,6 @@ eth_avp_dev_uninit(struct rte_eth_dev *eth_dev)
 		return ret;
 	}
 
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index 4b84b50c0..e89c0ec2c 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -718,9 +718,6 @@ eth_axgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 		return 0;
 
 	pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
-	/*Free macaddres*/
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c11fe9c8c..801c6ffad 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -3501,10 +3501,6 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev)
 	bnxt_disable_int(bp);
 	bnxt_free_int(bp);
 	bnxt_free_mem(bp);
-	if (eth_dev->data->mac_addrs != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
 	if (bp->grp_info != NULL) {
 		rte_free(bp->grp_info);
 		bp->grp_info = NULL;
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index b731132a5..77fb3dcd3 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3128,10 +3128,9 @@ bond_alloc(struct rte_vdev_device *dev, uint8_t mode)
 
 err:
 	rte_free(internals);
-	if (eth_dev != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		rte_eth_dev_release_port(eth_dev);
-	}
+	if (eth_dev != NULL)
+		eth_dev->data->dev_private = NULL;
+	rte_eth_dev_release_port(eth_dev);
 	return -1;
 }
 
@@ -3292,8 +3291,6 @@ bond_remove(struct rte_vdev_device *dev)
 	rte_mempool_free(internals->mode6.mempool);
 	rte_bitmap_free(internals->vlan_filter_bmp);
 	rte_free(internals->vlan_filter_bmpmem);
-	rte_free(eth_dev->data->dev_private);
-	rte_free(eth_dev->data->mac_addrs);
 
 	rte_eth_dev_release_port(eth_dev);
 
diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
index a135df9c7..88dc851f8 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -1710,12 +1710,7 @@ void cxgbe_close(struct adapter *adapter)
 			if (pi->viid != 0)
 				t4_free_vi(adapter, adapter->mbox,
 					   adapter->pf, 0, pi->viid);
-			rte_free(pi->eth_dev->data->mac_addrs);
-			/* Skip first port since it'll be freed by DPDK stack */
-			if (i) {
-				rte_free(pi->eth_dev->data->dev_private);
-				rte_eth_dev_release_port(pi->eth_dev);
-			}
+			rte_eth_dev_release_port(pi->eth_dev);
 		}
 		adapter->flags &= ~FULL_INIT_DONE;
 	}
@@ -1918,14 +1913,7 @@ int cxgbe_probe(struct adapter *adapter)
 		if (pi->viid != 0)
 			t4_free_vi(adapter, adapter->mbox, adapter->pf,
 				   0, pi->viid);
-		/* Skip first port since it'll be de-allocated by DPDK */
-		if (i == 0)
-			continue;
-		if (pi->eth_dev) {
-			if (pi->eth_dev->data->dev_private)
-				rte_free(pi->eth_dev->data->dev_private);
-			rte_eth_dev_release_port(pi->eth_dev);
-		}
+		rte_eth_dev_release_port(pi->eth_dev);
 	}
 
 	if (adapter->flags & FW_OK)
diff --git a/drivers/net/cxgbe/cxgbevf_main.c b/drivers/net/cxgbe/cxgbevf_main.c
index 4214d0312..6223e1250 100644
--- a/drivers/net/cxgbe/cxgbevf_main.c
+++ b/drivers/net/cxgbe/cxgbevf_main.c
@@ -282,14 +282,7 @@ int cxgbevf_probe(struct adapter *adapter)
 		if (pi->viid != 0)
 			t4_free_vi(adapter, adapter->mbox, adapter->pf,
 				   0, pi->viid);
-		/* Skip first port since it'll be de-allocated by DPDK */
-		if (i == 0)
-			continue;
-		if (pi->eth_dev) {
-			if (pi->eth_dev->data->dev_private)
-				rte_free(pi->eth_dev->data->dev_private);
-			rte_eth_dev_release_port(pi->eth_dev);
-		}
+		rte_eth_dev_release_port(pi->eth_dev);
 	}
 	return -err;
 }
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 5c743c3c8..d0572b3d9 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -1439,10 +1439,6 @@ dpaa_dev_uninit(struct rte_eth_dev *dev)
 	rte_free(dpaa_intf->tx_queues);
 	dpaa_intf->tx_queues = NULL;
 
-	/* free memory for storing MAC addresses */
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
@@ -1544,9 +1540,6 @@ rte_dpaa_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused,
 		return 0;
 	}
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 	return diag;
 }
@@ -1561,9 +1554,6 @@ rte_dpaa_remove(struct rte_dpaa_device *dpaa_dev)
 	eth_dev = dpaa_dev->eth_dev;
 	dpaa_dev_uninit(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 3987d13df..8267ee3f0 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -2065,12 +2065,6 @@ dpaa2_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	dpaa2_free_rx_tx_queues(eth_dev);
 
-	/* free memory for storing MAC addresses */
-	if (eth_dev->data->mac_addrs) {
-		rte_free(eth_dev->data->mac_addrs);
-		eth_dev->data->mac_addrs = NULL;
-	}
-
 	/* Close the device at underlying layer*/
 	ret = dpni_close(dpni, CMD_PRI_LOW, priv->token);
 	if (ret) {
@@ -2133,8 +2127,6 @@ rte_dpaa2_probe(struct rte_dpaa2_driver *dpaa2_drv,
 		return 0;
 	}
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 	return diag;
 }
@@ -2147,8 +2139,6 @@ rte_dpaa2_remove(struct rte_dpaa2_device *dpaa2_dev)
 	eth_dev = dpaa2_dev->eth_dev;
 	dpaa2_dev_uninit(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 28c153512..8230824e7 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -329,9 +329,6 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(intr_handle);
 	rte_intr_callback_unregister(intr_handle,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e542ef572..d9d29d22f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -917,9 +917,6 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* Reset any pending lock */
 	igb_reset_swfw_lock(hw);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* uninitialize PF if max_vfs not zero */
 	igb_pf_host_uninit(eth_dev);
 
@@ -1073,9 +1070,6 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(&pci_dev->intr_handle);
 	rte_intr_callback_unregister(&pci_dev->intr_handle,
diff --git a/drivers/net/enetc/enetc_ethdev.c b/drivers/net/enetc/enetc_ethdev.c
index 3ee7bb446..023fe7517 100644
--- a/drivers/net/enetc/enetc_ethdev.c
+++ b/drivers/net/enetc/enetc_ethdev.c
@@ -108,11 +108,9 @@ enetc_dev_init(struct rte_eth_dev *eth_dev)
 }
 
 static int
-enetc_dev_uninit(struct rte_eth_dev *eth_dev)
+enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused)
 {
 	PMD_INIT_FUNC_TRACE();
-	rte_free(eth_dev->data->mac_addrs);
-
 	return 0;
 }
 
diff --git a/drivers/net/failsafe/failsafe.c b/drivers/net/failsafe/failsafe.c
index c3999f026..fed36da5f 100644
--- a/drivers/net/failsafe/failsafe.c
+++ b/drivers/net/failsafe/failsafe.c
@@ -280,7 +280,8 @@ fs_eth_dev_create(struct rte_vdev_device *vdev)
 free_subs:
 	fs_sub_device_free(dev);
 free_dev:
-	rte_free(PRIV(dev));
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(dev);
 	return -1;
 }
@@ -305,7 +306,8 @@ fs_rte_eth_free(const char *name)
 	if (ret)
 		ERROR("Error while destroying hotplug mutex");
 	rte_free(PRIV(dev)->mcast_addrs);
-	rte_free(PRIV(dev));
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(dev);
 	return ret;
 }
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 46983e5df..bb7b906a9 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3234,14 +3234,6 @@ eth_fm10k_dev_uninit(struct rte_eth_dev *dev)
 			fm10k_dev_interrupt_handler_vf, (void *)dev);
 	}
 
-	/* free mac memory */
-	if (dev->data->mac_addrs) {
-		rte_free(dev->data->mac_addrs);
-		dev->data->mac_addrs = NULL;
-	}
-
-	memset(hw, 0, sizeof(*hw));
-
 	return 0;
 }
 
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index f7a685c8c..8a5c3c8fb 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1728,9 +1728,6 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	/* uninitialize pf host driver */
 	i40e_pf_host_uninit(dev);
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	/* disable uio intr before callback unregister */
 	rte_intr_disable(intr_handle);
 
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index baa6cc58f..ed2fc1310 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1483,9 +1483,6 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
 		return -1;
 	}
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/i40e/i40e_vf_representor.c b/drivers/net/i40e/i40e_vf_representor.c
index 24751d13c..43fe00cca 100644
--- a/drivers/net/i40e/i40e_vf_representor.c
+++ b/drivers/net/i40e/i40e_vf_representor.c
@@ -523,7 +523,10 @@ i40e_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params)
 }
 
 int
-i40e_vf_representor_uninit(struct rte_eth_dev *ethdev __rte_unused)
+i40e_vf_representor_uninit(struct rte_eth_dev *ethdev)
 {
+	/* mac_addrs must not be freed because part of i40e_pf_vf */
+	ethdev->data->mac_addrs = NULL;
+
 	return 0;
 }
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index c458bffc0..269595b73 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1337,12 +1337,6 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* uninitialize PF if max_vfs not zero */
 	ixgbe_pf_host_uninit(eth_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
-	rte_free(eth_dev->data->hash_mac_addrs);
-	eth_dev->data->hash_mac_addrs = NULL;
-
 	/* remove all the fdir filters & hash */
 	ixgbe_fdir_filter_uninit(eth_dev);
 
@@ -1722,9 +1716,6 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* Disable the interrupts for VF */
 	ixgbevf_intr_disable(eth_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	rte_intr_disable(intr_handle);
 	rte_intr_callback_unregister(intr_handle,
 				     ixgbevf_dev_interrupt_handler, eth_dev);
diff --git a/drivers/net/ixgbe/ixgbe_vf_representor.c b/drivers/net/ixgbe/ixgbe_vf_representor.c
index b0fbbc49f..eb9bbe5cb 100644
--- a/drivers/net/ixgbe/ixgbe_vf_representor.c
+++ b/drivers/net/ixgbe/ixgbe_vf_representor.c
@@ -225,7 +225,10 @@ ixgbe_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params)
 }
 
 int
-ixgbe_vf_representor_uninit(struct rte_eth_dev *ethdev __rte_unused)
+ixgbe_vf_representor_uninit(struct rte_eth_dev *ethdev)
 {
+	/* mac_addrs must not be freed because part of ixgbe_vf_info */
+	ethdev->data->mac_addrs = NULL;
+
 	return 0;
 }
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index 72f3c16c1..f43ee7d2e 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -463,6 +463,9 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	if (eth_dev == NULL)
 		return -1;
 
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
@@ -471,8 +474,6 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	internals = eth_dev->data->dev_private;
 	rte_kni_release(internals->kni);
 
-	rte_free(internals);
-
 	rte_eth_dev_release_port(eth_dev);
 
 	is_kni_initialized--;
diff --git a/drivers/net/liquidio/lio_ethdev.c b/drivers/net/liquidio/lio_ethdev.c
index 0f59e4475..d13ab06c0 100644
--- a/drivers/net/liquidio/lio_ethdev.c
+++ b/drivers/net/liquidio/lio_ethdev.c
@@ -2043,9 +2043,6 @@ lio_eth_dev_uninit(struct rte_eth_dev *eth_dev)
 	/* lio_free_sc_buffer_pool */
 	lio_free_sc_buffer_pool(lio_dev);
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 3de7bc53e..7f07b8dc0 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -781,12 +781,17 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 		continue;
 port_error:
 		rte_free(priv);
+		if (eth_dev != NULL)
+			eth_dev->data->dev_private = NULL;
 		if (pd)
 			claim_zero(mlx4_glue->dealloc_pd(pd));
 		if (ctx)
 			claim_zero(mlx4_glue->close_device(ctx));
-		if (eth_dev)
+		if (eth_dev != NULL) {
+			/* mac_addrs must not be freed because part of dev_private */
+			eth_dev->data->mac_addrs = NULL;
 			rte_eth_dev_release_port(eth_dev);
+		}
 		break;
 	}
 	/*
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 8cbfee1ba..b2be74b51 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1223,11 +1223,16 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		if (own_domain_id)
 			claim_zero(rte_eth_switch_domain_free(priv->domain_id));
 		rte_free(priv);
+		if (eth_dev != NULL)
+			eth_dev->data->dev_private = NULL;
 	}
 	if (pd)
 		claim_zero(mlx5_glue->dealloc_pd(pd));
-	if (eth_dev)
+	if (eth_dev != NULL) {
+		/* mac_addrs must not be freed alone because part of dev_private */
+		eth_dev->data->mac_addrs = NULL;
 		rte_eth_dev_release_port(eth_dev);
+	}
 	if (ctx)
 		claim_zero(mlx5_glue->close_device(ctx));
 	assert(err > 0);
@@ -1447,8 +1452,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 			if (!list[i].eth_dev)
 				continue;
 			mlx5_dev_close(list[i].eth_dev);
-			if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-				rte_free(list[i].eth_dev->data->dev_private);
+			/* mac_addrs must not be freed because in dev_private */
+			list[i].eth_dev->data->mac_addrs = NULL;
 			claim_zero(rte_eth_dev_release_port(list[i].eth_dev));
 		}
 		/* Restore original error. */
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index f7071bc2e..2d7666454 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -787,8 +787,9 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	priv = rte_zmalloc_socket(name, sizeof(*priv), 0, rte_socket_id());
 	if (!priv) {
 		ret = -ENOMEM;
-		goto out_free_dev;
+		goto out_free;
 	}
+	eth_dev->data->dev_private = priv;
 
 	eth_dev->data->mac_addrs =
 		rte_zmalloc("mac_addrs",
@@ -796,20 +797,19 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	if (!eth_dev->data->mac_addrs) {
 		MVNETA_LOG(ERR, "Failed to allocate space for eth addrs");
 		ret = -ENOMEM;
-		goto out_free_priv;
+		goto out_free;
 	}
 
 	memset(&req, 0, sizeof(req));
 	strcpy(req.ifr_name, name);
 	ret = ioctl(fd, SIOCGIFHWADDR, &req);
 	if (ret)
-		goto out_free_mac;
+		goto out_free;
 
 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
 
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
-	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
 	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
 	mvneta_set_tx_function(eth_dev);
@@ -817,11 +817,7 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 
 	rte_eth_dev_probing_finish(eth_dev);
 	return 0;
-out_free_mac:
-	rte_free(eth_dev->data->mac_addrs);
-out_free_priv:
-	rte_free(priv);
-out_free_dev:
+out_free:
 	rte_eth_dev_release_port(eth_dev);
 
 	return ret;
@@ -836,8 +832,6 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 static void
 mvneta_eth_dev_destroy(struct rte_eth_dev *eth_dev)
 {
-	rte_free(eth_dev->data->dev_private);
-	rte_free(eth_dev->data->mac_addrs);
 	rte_eth_dev_release_port(eth_dev);
 }
 
diff --git a/drivers/net/mvpp2/mrvl_ethdev.c b/drivers/net/mvpp2/mrvl_ethdev.c
index 0682c635a..ab4c14e51 100644
--- a/drivers/net/mvpp2/mrvl_ethdev.c
+++ b/drivers/net/mvpp2/mrvl_ethdev.c
@@ -2780,8 +2780,9 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	priv = mrvl_priv_create(name);
 	if (!priv) {
 		ret = -ENOMEM;
-		goto out_free_dev;
+		goto out_free;
 	}
+	eth_dev->data->dev_private = priv;
 
 	eth_dev->data->mac_addrs =
 		rte_zmalloc("mac_addrs",
@@ -2789,20 +2790,19 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	if (!eth_dev->data->mac_addrs) {
 		MRVL_LOG(ERR, "Failed to allocate space for eth addrs");
 		ret = -ENOMEM;
-		goto out_free_priv;
+		goto out_free;
 	}
 
 	memset(&req, 0, sizeof(req));
 	strcpy(req.ifr_name, name);
 	ret = ioctl(fd, SIOCGIFHWADDR, &req);
 	if (ret)
-		goto out_free_mac;
+		goto out_free;
 
 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
 
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
-	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
 	eth_dev->rx_pkt_burst = mrvl_rx_pkt_burst;
 	mrvl_set_tx_function(eth_dev);
@@ -2810,12 +2810,8 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 
 	rte_eth_dev_probing_finish(eth_dev);
 	return 0;
-out_free_mac:
-	rte_free(eth_dev->data->mac_addrs);
-out_free_dev:
+out_free:
 	rte_eth_dev_release_port(eth_dev);
-out_free_priv:
-	rte_free(priv);
 
 	return ret;
 }
@@ -2839,8 +2835,6 @@ mrvl_eth_dev_destroy(const char *name)
 	priv = eth_dev->data->dev_private;
 	pp2_bpool_deinit(priv->bpool);
 	used_bpools[priv->pp_id] &= ~(1 << priv->bpool_bit);
-	rte_free(priv);
-	rte_free(eth_dev->data->mac_addrs);
 	rte_eth_dev_release_port(eth_dev);
 }
 
diff --git a/drivers/net/netvsc/hn_ethdev.c b/drivers/net/netvsc/hn_ethdev.c
index 8e728d639..aa38ee7a3 100644
--- a/drivers/net/netvsc/hn_ethdev.c
+++ b/drivers/net/netvsc/hn_ethdev.c
@@ -118,20 +118,11 @@ eth_dev_vmbus_allocate(struct rte_vmbus_device *dev, size_t private_data_size)
 static void
 eth_dev_vmbus_release(struct rte_eth_dev *eth_dev)
 {
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
 	/* free ether device */
 	rte_eth_dev_release_port(eth_dev);
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(eth_dev->data->dev_private);
-
-	eth_dev->data->dev_private = NULL;
-
-	/*
-	 * Secondary process will check the name to attach.
-	 * Clear this field to avoid attaching a released ports.
-	 */
-	eth_dev->data->name[0] = '\0';
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 }
@@ -829,8 +820,6 @@ eth_hn_dev_uninit(struct rte_eth_dev *eth_dev)
 	rte_free(hv->primary);
 	rte_eth_dev_owner_delete(hv->owner.id);
 
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index 1e8237a41..b77283ae7 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -682,8 +682,8 @@ rte_pmd_null_remove(struct rte_vdev_device *dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
-	rte_free(eth_dev->data->dev_private);
-
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index 5431b44dc..746507912 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -1015,12 +1015,22 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 		return 0;
 	}
 
+	/* Reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(octtx_name);
+	if (eth_dev == NULL) {
+		octeontx_log_err("failed to allocate rte_eth_dev");
+		res = -ENOMEM;
+		goto err;
+	}
+	data = eth_dev->data;
+
 	nic = rte_zmalloc_socket(octtx_name, sizeof(*nic), 0, socket_id);
 	if (nic == NULL) {
 		octeontx_log_err("failed to allocate nic structure");
 		res = -ENOMEM;
 		goto err;
 	}
+	data->dev_private = nic;
 
 	nic->port_id = port;
 	nic->evdev = evdev;
@@ -1037,21 +1047,11 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 		goto err;
 	}
 
-	/* Reserve an ethdev entry */
-	eth_dev = rte_eth_dev_allocate(octtx_name);
-	if (eth_dev == NULL) {
-		octeontx_log_err("failed to allocate rte_eth_dev");
-		res = -ENOMEM;
-		goto err;
-	}
-
 	eth_dev->device = &dev->device;
 	eth_dev->intr_handle = NULL;
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->numa_node = dev->device.numa_node;
 
-	data = eth_dev->data;
-	data->dev_private = nic;
 	data->port_id = eth_dev->data->port_id;
 
 	nic->ev_queues = 1;
@@ -1103,12 +1103,7 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 	if (nic)
 		octeontx_port_close(nic);
 
-	if (eth_dev != NULL) {
-		rte_free(eth_dev->data->mac_addrs);
-		rte_free(data);
-		rte_free(nic);
-		rte_eth_dev_release_port(eth_dev);
-	}
+	rte_eth_dev_release_port(eth_dev);
 
 	return res;
 }
@@ -1142,8 +1137,6 @@ octeontx_remove(struct rte_vdev_device *dev)
 		rte_event_dev_stop(nic->evdev);
 		PMD_INIT_LOG(INFO, "Closing octeontx device %s", octtx_name);
 
-		rte_free(eth_dev->data->mac_addrs);
-		rte_free(eth_dev->data->dev_private);
 		rte_eth_dev_release_port(eth_dev);
 		rte_event_dev_close(nic->evdev);
 	}
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index ede5ebb45..1790a8064 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -1232,11 +1232,9 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
 	internals = eth_dev->data->dev_private;
-	if (internals && internals->phy_mac)
-		rte_free(eth_dev->data->mac_addrs);
-
-	rte_free(eth_dev->data->dev_private);
-
+	if (internals != NULL && internals->phy_mac == 0)
+		/* not dynamically allocated, must not be freed */
+		eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index 18d244a93..404859426 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2666,11 +2666,6 @@ static int qede_dev_common_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
 
-	if (eth_dev->data->mac_addrs)
-		rte_free(eth_dev->data->mac_addrs);
-
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/drivers/net/ring/rte_eth_ring.c b/drivers/net/ring/rte_eth_ring.c
index bfe2f1780..aeb48f5ec 100644
--- a/drivers/net/ring/rte_eth_ring.c
+++ b/drivers/net/ring/rte_eth_ring.c
@@ -666,10 +666,8 @@ rte_pmd_ring_remove(struct rte_vdev_device *dev)
 		}
 	}
 
-	rte_free(eth_dev->data->rx_queues);
-	rte_free(eth_dev->data->tx_queues);
-	rte_free(eth_dev->data->dev_private);
-
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 	return 0;
 }
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index b2e17f26e..3886daf7a 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -2035,9 +2035,6 @@ sfc_eth_dev_uninit(struct rte_eth_dev *dev)
 	sfc_detach(sa);
 	sfc_unprobe(sa);
 
-	rte_free(dev->data->mac_addrs);
-	dev->data->mac_addrs = NULL;
-
 	sfc_kvargs_cleanup(sa);
 
 	sfc_adapter_unlock(sa);
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 0fd264e25..9a2418438 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -556,7 +556,6 @@ static int
 pmd_remove(struct rte_vdev_device *vdev)
 {
 	struct rte_eth_dev *dev = NULL;
-	struct pmd_internals *p;
 
 	if (!vdev)
 		return -EINVAL;
@@ -567,12 +566,12 @@ pmd_remove(struct rte_vdev_device *vdev)
 	dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
 	if (dev == NULL)
 		return -ENODEV;
-	p = dev->data->dev_private;
 
 	/* Free device data structures*/
-	rte_free(dev->data);
+	pmd_free(dev->data->dev_private);
+	dev->data->dev_private = NULL; /* already freed */
+	dev->data->mac_addrs = NULL; /* statically allocated */
 	rte_eth_dev_release_port(dev);
-	pmd_free(p);
 
 	return 0;
 }
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index 4e5e01cf1..88448eff6 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1544,7 +1544,6 @@ rte_szedata2_eth_dev_uninit(struct rte_eth_dev *dev)
 	PMD_INIT_FUNC_TRACE();
 
 	free(internals->sze_dev_path);
-	rte_free(dev->data->mac_addrs);
 
 	PMD_DRV_LOG(INFO, "%s device %s successfully uninitialized",
 			RTE_STR(RTE_SZEDATA2_DRIVER_NAME), dev->data->name);
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 84aaf2410..2327fbf8c 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1808,6 +1808,8 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, char *tap_name,
 error_exit:
 	if (pmd->ioctl_sock > 0)
 		close(pmd->ioctl_sock);
+	/* mac_addrs must not be freed alone because part of dev_private */
+	dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(dev);
 
 error_exit_nodev:
@@ -2076,6 +2078,9 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	if (!eth_dev)
 		return -ENODEV;
 
+	/* mac_addrs must not be freed alone because part of dev_private */
+	eth_dev->data->mac_addrs = NULL;
+
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(eth_dev);
 
@@ -2102,7 +2107,6 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	}
 
 	close(internals->ioctl_sock);
-	rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	if (internals->ka_fd != -1) {
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index a7604ff23..cf51c072d 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -1220,10 +1220,12 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internal));
 	if (eth_dev == NULL)
 		goto error;
+	data = eth_dev->data;
 
 	eth_addr = rte_zmalloc_socket(name, sizeof(*eth_addr), 0, numa_node);
 	if (eth_addr == NULL)
 		goto error;
+	data->mac_addrs = eth_addr;
 	*eth_addr = base_eth_addr;
 	eth_addr->addr_bytes[5] = eth_dev->data->port_id;
 
@@ -1253,13 +1255,11 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	rte_spinlock_init(&vring_state->lock);
 	vring_states[eth_dev->data->port_id] = vring_state;
 
-	data = eth_dev->data;
 	data->nb_rx_queues = queues;
 	data->nb_tx_queues = queues;
 	internal->max_queues = queues;
 	internal->vid = -1;
 	data->dev_link = pmd_link;
-	data->mac_addrs = eth_addr;
 	data->dev_flags = RTE_ETH_DEV_INTR_LSC;
 
 	eth_dev->dev_ops = &ops;
@@ -1291,10 +1291,7 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 		free(internal->dev_name);
 	}
 	rte_free(vring_state);
-	rte_free(eth_addr);
-	if (eth_dev)
-		rte_eth_dev_release_port(eth_dev);
-	rte_free(internal);
+	rte_eth_dev_release_port(eth_dev);
 	rte_free(list);
 
 	return -1;
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 730c41707..10a7e3fcc 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1706,9 +1706,6 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->tx_pkt_burst = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	/* reset interrupt callback  */
 	if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
 		rte_intr_callback_unregister(eth_dev->intr_handle,
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 525d16cab..420364b7a 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -422,7 +422,6 @@ virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev)
 	if (!dev) {
 		PMD_INIT_LOG(ERR, "malloc virtio_user_dev failed");
 		rte_eth_dev_release_port(eth_dev);
-		rte_free(hw);
 		return NULL;
 	}
 
@@ -449,7 +448,6 @@ virtio_user_eth_dev_free(struct rte_eth_dev *eth_dev)
 	struct virtio_hw *hw = data->dev_private;
 
 	rte_free(hw->virtio_user_dev);
-	rte_free(hw);
 	rte_eth_dev_release_port(eth_dev);
 }
 
@@ -662,7 +660,6 @@ virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 	dev = hw->virtio_user_dev;
 	virtio_user_dev_uninit(dev);
 
-	rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 78e5b7680..41bcd450a 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -368,9 +368,6 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->tx_pkt_burst = NULL;
 	eth_dev->tx_pkt_prepare = NULL;
 
-	rte_free(eth_dev->data->mac_addrs);
-	eth_dev->data->mac_addrs = NULL;
-
 	return 0;
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 571f0e850..3bc05f4c3 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -388,7 +388,14 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 
 	eth_dev->state = RTE_ETH_DEV_UNUSED;
 
-	memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		rte_free(eth_dev->data->rx_queues);
+		rte_free(eth_dev->data->tx_queues);
+		rte_free(eth_dev->data->mac_addrs);
+		rte_free(eth_dev->data->hash_mac_addrs);
+		rte_free(eth_dev->data->dev_private);
+		memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
+	}
 
 	rte_spinlock_unlock(&rte_eth_dev_shared_data->ownership_lock);
 
@@ -3529,7 +3536,7 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 			if (!ethdev->data->dev_private) {
 				RTE_LOG(ERR, EAL, "failed to allocate private data");
 				retval = -ENOMEM;
-				goto data_alloc_failed;
+				goto probe_failed;
 			}
 		}
 	} else {
@@ -3561,14 +3568,9 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 	rte_eth_dev_probing_finish(ethdev);
 
 	return retval;
-probe_failed:
-	/* free ports private data if primary process */
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
-		rte_free(ethdev->data->dev_private);
 
-data_alloc_failed:
+probe_failed:
 	rte_eth_dev_release_port(ethdev);
-
 	return retval;
 }
 
@@ -3592,9 +3594,6 @@ rte_eth_dev_destroy(struct rte_eth_dev *ethdev,
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port_secondary(ethdev);
 
-	rte_free(ethdev->data->dev_private);
-	ethdev->data->dev_private = NULL;
-
 	return rte_eth_dev_release_port(ethdev);
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev_core.h b/lib/librte_ethdev/rte_ethdev_core.h
index 03ec4992a..9fb826e1d 100644
--- a/lib/librte_ethdev/rte_ethdev_core.h
+++ b/lib/librte_ethdev/rte_ethdev_core.h
@@ -579,7 +579,10 @@ struct rte_eth_dev_data {
 
 	struct rte_eth_dev_sriov sriov;    /**< SRIOV data */
 
-	void *dev_private;              /**< PMD-specific private data */
+	void *dev_private;
+			/**< PMD-specific private data.
+			 *   @see rte_eth_dev_release_port()
+			 */
 
 	struct rte_eth_link dev_link;   /**< Link-level information & status. */
 	struct rte_eth_conf dev_conf;   /**< Configuration applied to device. */
@@ -588,11 +591,16 @@ struct rte_eth_dev_data {
 			/**< Common RX buffer size handled by all queues. */
 
 	uint64_t rx_mbuf_alloc_failed; /**< RX ring mbuf allocation failures. */
-	struct ether_addr *mac_addrs;  /**< Device Ethernet link address. */
+	struct ether_addr *mac_addrs;
+			/**< Device Ethernet link address.
+			 *   @see rte_eth_dev_release_port()
+			 */
 	uint64_t mac_pool_sel[ETH_NUM_RECEIVE_MAC_ADDR];
 			/**< Bitmap associating MAC addresses to pools. */
 	struct ether_addr *hash_mac_addrs;
-			/**< Device Ethernet MAC addresses of hash filtering. */
+			/**< Device Ethernet MAC addresses of hash filtering.
+			 *   @see rte_eth_dev_release_port()
+			 */
 	uint16_t port_id;           /**< Device [external] port identifier. */
 
 	__extension__
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index ca31b5777..66274be7a 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -58,7 +58,14 @@ struct rte_eth_dev *rte_eth_dev_attach_secondary(const char *name);
 
 /**
  * @internal
- * Release the specified ethdev port.
+ * Notify RTE_ETH_EVENT_DESTROY and release the specified ethdev port.
+ *
+ * The following PMD-managed data fields will be freed:
+ *   - dev_private
+ *   - mac_addrs
+ *   - hash_mac_addrs
+ * If one of these fields should not be freed,
+ * it must be reset to NULL by the PMD, typically in dev_close method.
  *
  * @param eth_dev
  * Device to be detached.
diff --git a/lib/librte_ethdev/rte_ethdev_pci.h b/lib/librte_ethdev/rte_ethdev_pci.h
index 70d2d2503..8ff4f6b89 100644
--- a/lib/librte_ethdev/rte_ethdev_pci.h
+++ b/lib/librte_ethdev/rte_ethdev_pci.h
@@ -142,16 +142,6 @@ rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev)
 		return;
 	}
 
-	/* primary process */
-	rte_free(eth_dev->data->dev_private);
-	eth_dev->data->dev_private = NULL;
-
-	/*
-	 * Secondary process will check the name to attach.
-	 * Clear this field to avoid attaching a released ports.
-	 */
-	eth_dev->data->name[0] = '\0';
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v6 5/6] ethdev: remove release function for secondary process
  2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
                     ` (3 preceding siblings ...)
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 4/6] ethdev: free all common data when releasing port Thomas Monjalon
@ 2018-10-19  2:07   ` Thomas Monjalon
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 6/6] ethdev: complete closing of port Thomas Monjalon
  2018-10-22 15:43   ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Ferruh Yigit
  6 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-19  2:07 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

After previous changes, the function rte_eth_dev_release_port()
can be used for primary or secondary process as well.
The only difference with rte_eth_dev_release_port_secondary()
is the shared lock used in rte_eth_dev_release_port().

The function rte_eth_dev_release_port_secondary() was recently
added in 18.11 cycle.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/net/af_packet/rte_eth_af_packet.c |  2 +-
 drivers/net/bonding/rte_eth_bond_pmd.c    |  2 +-
 drivers/net/kni/rte_eth_kni.c             |  2 +-
 drivers/net/null/rte_eth_null.c           |  7 +++----
 drivers/net/octeontx/octeontx_ethdev.c    |  2 +-
 drivers/net/pcap/rte_eth_pcap.c           | 12 ++++++------
 drivers/net/tap/rte_eth_tap.c             |  2 +-
 drivers/net/vhost/rte_eth_vhost.c         |  2 +-
 lib/librte_ethdev/rte_ethdev.c            | 15 ---------------
 lib/librte_ethdev/rte_ethdev_driver.h     | 14 --------------
 lib/librte_ethdev/rte_ethdev_pci.h        |  7 -------
 lib/librte_ethdev/rte_ethdev_version.map  |  7 -------
 12 files changed, 15 insertions(+), 59 deletions(-)

diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 2efc17725..95a98c6b8 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -990,7 +990,7 @@ rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
 	eth_dev->data->mac_addrs = NULL;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	internals = eth_dev->data->dev_private;
 	for (q = 0; q < internals->nb_queues; q++) {
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 77fb3dcd3..e7a4be921 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3267,7 +3267,7 @@ bond_remove(struct rte_vdev_device *dev)
 		return -ENODEV;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	RTE_ASSERT(eth_dev->device == &dev->device);
 
diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
index f43ee7d2e..a1e9970df 100644
--- a/drivers/net/kni/rte_eth_kni.c
+++ b/drivers/net/kni/rte_eth_kni.c
@@ -467,7 +467,7 @@ eth_kni_remove(struct rte_vdev_device *vdev)
 	eth_dev->data->mac_addrs = NULL;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	eth_kni_dev_stop(eth_dev);
 
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index b77283ae7..159c1c1fd 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -679,11 +679,10 @@ rte_pmd_null_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		/* mac_addrs must not be freed alone because part of dev_private */
+		eth_dev->data->mac_addrs = NULL;
 
-	/* mac_addrs must not be freed alone because part of dev_private */
-	eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index 746507912..068148624 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -1129,7 +1129,7 @@ octeontx_remove(struct rte_vdev_device *dev)
 			return -ENODEV;
 
 		if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
-			rte_eth_dev_release_port_secondary(eth_dev);
+			rte_eth_dev_release_port(eth_dev);
 			continue;
 		}
 
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 1790a8064..7bbe72e25 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -1228,13 +1228,13 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
 	if (eth_dev == NULL)
 		return -1;
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		internals = eth_dev->data->dev_private;
+		if (internals != NULL && internals->phy_mac == 0)
+			/* not dynamically allocated, must not be freed */
+			eth_dev->data->mac_addrs = NULL;
+	}
 
-	internals = eth_dev->data->dev_private;
-	if (internals != NULL && internals->phy_mac == 0)
-		/* not dynamically allocated, must not be freed */
-		eth_dev->data->mac_addrs = NULL;
 	rte_eth_dev_release_port(eth_dev);
 
 	return 0;
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 2327fbf8c..53d37b3cb 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -2082,7 +2082,7 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	eth_dev->data->mac_addrs = NULL;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	internals = eth_dev->data->dev_private;
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index cf51c072d..0cd1a4642 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -1433,7 +1433,7 @@ rte_pmd_vhost_remove(struct rte_vdev_device *dev)
 		return -ENODEV;
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(eth_dev);
+		return rte_eth_dev_release_port(eth_dev);
 
 	eth_dev_close(eth_dev);
 
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 3bc05f4c3..178800a5b 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -362,18 +362,6 @@ rte_eth_dev_attach_secondary(const char *name)
 	return eth_dev;
 }
 
-int
-rte_eth_dev_release_port_secondary(struct rte_eth_dev *eth_dev)
-{
-	if (eth_dev == NULL)
-		return -EINVAL;
-
-	_rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_DESTROY, NULL);
-	eth_dev->state = RTE_ETH_DEV_UNUSED;
-
-	return 0;
-}
-
 int
 rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 {
@@ -3591,9 +3579,6 @@ rte_eth_dev_destroy(struct rte_eth_dev *ethdev,
 			return ret;
 	}
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return rte_eth_dev_release_port_secondary(ethdev);
-
 	return rte_eth_dev_release_port(ethdev);
 }
 
diff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h
index 66274be7a..c2ac26328 100644
--- a/lib/librte_ethdev/rte_ethdev_driver.h
+++ b/lib/librte_ethdev/rte_ethdev_driver.h
@@ -74,20 +74,6 @@ struct rte_eth_dev *rte_eth_dev_attach_secondary(const char *name);
  */
 int rte_eth_dev_release_port(struct rte_eth_dev *eth_dev);
 
-/**
- * @internal
- * Release the specified ethdev port in the local process.
- * Only set ethdev state to unused, but not reset shared data since
- * it assume other processes is still using it. typically it is
- * called by a secondary process.
- *
- * @param eth_dev
- * Device to be detached.
- * @return
- *   - 0 on success, negative on error
- */
-int rte_eth_dev_release_port_secondary(struct rte_eth_dev *eth_dev);
-
 /**
  * @internal
  * Release device queues and clear its configuration to force the user
diff --git a/lib/librte_ethdev/rte_ethdev_pci.h b/lib/librte_ethdev/rte_ethdev_pci.h
index 8ff4f6b89..23257e986 100644
--- a/lib/librte_ethdev/rte_ethdev_pci.h
+++ b/lib/librte_ethdev/rte_ethdev_pci.h
@@ -135,13 +135,6 @@ rte_eth_dev_pci_allocate(struct rte_pci_device *dev, size_t private_data_size)
 static inline void
 rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev)
 {
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
-		eth_dev->device = NULL;
-		eth_dev->intr_handle = NULL;
-		rte_eth_dev_release_port_secondary(eth_dev);
-		return;
-	}
-
 	eth_dev->device = NULL;
 	eth_dev->intr_handle = NULL;
 
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 3a4dd4790..dfa122c1a 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -220,13 +220,6 @@ DPDK_18.08 {
 
 } DPDK_18.05;
 
-DPDK_18.11 {
-	global:
-
-	rte_eth_dev_release_port_secondary;
-
-} DPDK_18.08;
-
 EXPERIMENTAL {
 	global:
 
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [dpdk-dev] [PATCH v6 6/6] ethdev: complete closing of port
  2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
                     ` (4 preceding siblings ...)
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 5/6] ethdev: remove release function for secondary process Thomas Monjalon
@ 2018-10-19  2:07   ` Thomas Monjalon
  2018-10-19 10:13     ` Andrew Rybchenko
  2018-10-22 15:43   ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Ferruh Yigit
  6 siblings, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2018-10-19  2:07 UTC (permalink / raw)
  To: ferruh.yigit, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

After closing a port, it cannot be restarted.
So there is no reason to not free all associated resources.

The last step was done with rte_eth_dev_detach() which is deprecated.
Instead of blindly removing the associated rte_device, the driver should
check if no more port (ethdev, cryptodev, etc) is open for the device.

The last ethdev freeing which were done by rte_eth_dev_detach(),
are now done at the end of rte_eth_dev_close() if the driver supports
the flag RTE_ETH_DEV_CLOSE_REMOVE.
There will be a transition period for PMDs to enable this new flag
and migrate to the new behaviour.
When enabling RTE_ETH_DEV_CLOSE_REMOVE, the PMD must free all its
private resources for the port, in its dev_close function.
It is advised to call the dev_close function in the remove function
in order to support removing a device without closing its ports.

Some drivers does not allocate MAC addresses dynamically or separately.
In those cases, the pointer is set to NULL, in order to avoid wrongly
freeing them in rte_eth_dev_release_port().

A closed port will have the state RTE_ETH_DEV_UNUSED which is
considered as invalid by rte_eth_dev_is_valid_port().
So validity is not checked anymore for closed ports in testpmd.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 app/test-pmd/testpmd.c                 | 16 +++-------------
 doc/guides/rel_notes/release_18_11.rst |  5 +++++
 lib/librte_ethdev/rte_ethdev.c         | 10 ++++++++++
 lib/librte_ethdev/rte_ethdev.h         |  9 +++++++--
 4 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index d5a8a14af..b0b418424 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1938,18 +1938,6 @@ port_is_started(portid_t port_id)
 	return 1;
 }
 
-static int
-port_is_closed(portid_t port_id)
-{
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return 0;
-
-	if (ports[port_id].port_status != RTE_PORT_CLOSED)
-		return 0;
-
-	return 1;
-}
-
 int
 start_port(portid_t pid)
 {
@@ -2253,6 +2241,8 @@ close_port(portid_t pid)
 			port_flow_flush(pi);
 		rte_eth_dev_close(pi);
 
+		remove_unused_fwd_ports();
+
 		if (rte_atomic16_cmpset(&(port->port_status),
 			RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0)
 			printf("Port %d cannot be set to closed\n", pi);
@@ -2343,7 +2333,7 @@ detach_port(portid_t port_id)
 
 	printf("Detaching a port...\n");
 
-	if (!port_is_closed(port_id)) {
+	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
 		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
 			printf("Port not stopped\n");
 			return;
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 3d5a34ed9..1cbc93d9d 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -235,6 +235,11 @@ API Changes
   functions were deprecated since 17.05 and are replaced by
   ``rte_mbuf_raw_free()`` and ``rte_pktmbuf_prefree_seg()``.
 
+* ethdev: A call to ``rte_eth_dev_release_port()`` has been added in
+  ``rte_eth_dev_close()``. As a consequence, a closed port is freed
+  and seen as invalid because of its state ``RTE_ETH_DEV_UNUSED``.
+  This new behaviour is enabled per driver for a migration period.
+
 * A new device flag, RTE_ETH_DEV_NOLIVE_MAC_ADDR, changes the order of
   actions inside rte_eth_dev_start regarding MAC set. Some NICs do not
   support MAC changes once the port has started and with this new device
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 178800a5b..0979c0c7b 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -1384,6 +1384,16 @@ rte_eth_dev_close(uint16_t port_id)
 	dev->data->dev_started = 0;
 	(*dev->dev_ops->dev_close)(dev);
 
+	/* check behaviour flag - temporary for PMD migration */
+	if ((dev->data->dev_flags & RTE_ETH_DEV_CLOSE_REMOVE) != 0) {
+		/* new behaviour: send event + reset state + free all data */
+		rte_eth_dev_release_port(dev);
+		return;
+	}
+	RTE_ETHDEV_LOG(DEBUG, "Port closing is using an old behaviour.\n"
+			"The driver %s should migrate to the new behaviour.\n",
+			dev->device->driver->name);
+	/* old behaviour: only free queue arrays */
 	dev->data->nb_rx_queues = 0;
 	rte_free(dev->data->rx_queues);
 	dev->data->rx_queues = NULL;
diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h
index fb40c89e0..c4caf0642 100644
--- a/lib/librte_ethdev/rte_ethdev.h
+++ b/lib/librte_ethdev/rte_ethdev.h
@@ -1259,6 +1259,11 @@ struct rte_eth_dev_owner {
 	char name[RTE_ETH_MAX_OWNER_NAME_LEN]; /**< The owner name. */
 };
 
+/**
+ * Port is released (i.e. totally freed and data erased) on close.
+ * Temporary flag for PMD migration to new rte_eth_dev_close() behaviour.
+ */
+#define RTE_ETH_DEV_CLOSE_REMOVE 0x0001
 /** Device supports link state interrupt */
 #define RTE_ETH_DEV_INTR_LSC     0x0002
 /** Device is a bonded slave */
@@ -1802,8 +1807,8 @@ int rte_eth_dev_set_link_down(uint16_t port_id);
 
 /**
  * Close a stopped Ethernet device. The device cannot be restarted!
- * The function frees all resources except for needed by the
- * closed state. To free these resources, call rte_eth_dev_detach().
+ * The function frees all port resources if the driver supports
+ * the flag RTE_ETH_DEV_CLOSE_REMOVE.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
-- 
2.19.0

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v6 6/6] ethdev: complete closing of port
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 6/6] ethdev: complete closing of port Thomas Monjalon
@ 2018-10-19 10:13     ` Andrew Rybchenko
  0 siblings, 0 replies; 78+ messages in thread
From: Andrew Rybchenko @ 2018-10-19 10:13 UTC (permalink / raw)
  To: Thomas Monjalon, ferruh.yigit
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

On 10/19/18 5:07 AM, Thomas Monjalon wrote:
> After closing a port, it cannot be restarted.
> So there is no reason to not free all associated resources.
>
> The last step was done with rte_eth_dev_detach() which is deprecated.
> Instead of blindly removing the associated rte_device, the driver should
> check if no more port (ethdev, cryptodev, etc) is open for the device.
>
> The last ethdev freeing which were done by rte_eth_dev_detach(),
> are now done at the end of rte_eth_dev_close() if the driver supports
> the flag RTE_ETH_DEV_CLOSE_REMOVE.
> There will be a transition period for PMDs to enable this new flag
> and migrate to the new behaviour.
> When enabling RTE_ETH_DEV_CLOSE_REMOVE, the PMD must free all its
> private resources for the port, in its dev_close function.
> It is advised to call the dev_close function in the remove function
> in order to support removing a device without closing its ports.
>
> Some drivers does not allocate MAC addresses dynamically or separately.
> In those cases, the pointer is set to NULL, in order to avoid wrongly
> freeing them in rte_eth_dev_release_port().
>
> A closed port will have the state RTE_ETH_DEV_UNUSED which is
> considered as invalid by rte_eth_dev_is_valid_port().
> So validity is not checked anymore for closed ports in testpmd.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>

I really like the idea with RTE_ETH_DEV_CLOSE_REMOVE.

As I understand it should applied to dpdk-next-net, but
right now there are conflicts in net/tap (patch 4).

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v6 1/6] app/testpmd: update port list for multiple removals
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 1/6] app/testpmd: update port list for multiple removals Thomas Monjalon
@ 2018-10-19 14:32     ` Iremonger, Bernard
  0 siblings, 0 replies; 78+ messages in thread
From: Iremonger, Bernard @ 2018-10-19 14:32 UTC (permalink / raw)
  To: Thomas Monjalon, Yigit, Ferruh, arybchenko
  Cc: dev, ophirmu, rahul.lakkireddy, Wisam Jaddo

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Friday, October 19, 2018 3:08 AM
> To: Yigit, Ferruh <ferruh.yigit@intel.com>; arybchenko@solarflare.com
> Cc: dev@dpdk.org; ophirmu@mellanox.com; Iremonger, Bernard
> <bernard.iremonger@intel.com>; rahul.lakkireddy@chelsio.com; Wisam
> Jaddo <wisamm@mellanox.com>
> Subject: [PATCH v6 1/6] app/testpmd: update port list for multiple removals
> 
> From: Wisam Jaddo <wisamm@mellanox.com>
> 
> When detaching a port, the full rte_device is removed.
> If the rte_device was hosting several ports, the testpmd list of ports must be
> updated for multiple removals.
> 
> Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
Acked-by: Bernard Iremonger <bernard.iremonger@intel.com>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v6 2/6] app/testpmd: allow detaching a port not closed
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 2/6] app/testpmd: allow detaching a port not closed Thomas Monjalon
@ 2018-10-19 14:32     ` Iremonger, Bernard
  0 siblings, 0 replies; 78+ messages in thread
From: Iremonger, Bernard @ 2018-10-19 14:32 UTC (permalink / raw)
  To: Thomas Monjalon, Yigit, Ferruh, arybchenko; +Cc: dev, ophirmu, rahul.lakkireddy

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Friday, October 19, 2018 3:08 AM
> To: Yigit, Ferruh <ferruh.yigit@intel.com>; arybchenko@solarflare.com
> Cc: dev@dpdk.org; ophirmu@mellanox.com; Iremonger, Bernard
> <bernard.iremonger@intel.com>; rahul.lakkireddy@chelsio.com
> Subject: [PATCH v6 2/6] app/testpmd: allow detaching a port not closed
> 
> The testpmd application aim is for testing; so order of operations should not
> be enforced.
> 
> There was a test to forbid detaching before closing a port.
> However, it may interesting to test what happens in such case.
> It is possible for a PMD to automatically close the port when detaching.
> 
> in order to avoid a crash, it is checked that the port must be stopped before
> detaching (as for closing).
> 
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Acked-by: Bernard Iremonger <bernard.iremonger@intel.com>

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [dpdk-dev] [PATCH v6 0/6] ethdev port freeing
  2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
                     ` (5 preceding siblings ...)
  2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 6/6] ethdev: complete closing of port Thomas Monjalon
@ 2018-10-22 15:43   ` Ferruh Yigit
  6 siblings, 0 replies; 78+ messages in thread
From: Ferruh Yigit @ 2018-10-22 15:43 UTC (permalink / raw)
  To: Thomas Monjalon, arybchenko
  Cc: dev, ophirmu, bernard.iremonger, rahul.lakkireddy

On 10/19/2018 3:07 AM, Thomas Monjalon wrote:
> The function rte_eth_dev_detach() is freeing a port and its underlying
> rte_device object. The issue is that we may have several ports
> associated to the same rte_device.
> 
> The right replacement is to free the port, and free the rte_device
> if no more ports.
> At ethdev level, the public function for port freeing is rte_eth_dev_close().
> The only miss is rte_eth_dev_release_port() to free all port resources.
> 
> This patchset does a cleanup by moving as much ethdev data freeing
> as possible in an unique function rte_eth_dev_release_port(),
> and call this function in rte_eth_dev_close().
> The port is released on close only if the driver supports it.
> 
> 
> Changes in v6:
>   - fix testpmd ports list iteration
>   - keep old behaviour
>   - add flag RTE_ETH_DEV_CLOSE_REMOVE to enable new behaviour (port release)
> 
> Changes in v5:
>   - fix testpmd for detaching multi-ports device
>   - fix testpmd for detaching only stopped ports
>   - add a release note about closed port freeing and state
>   - fix some doxygen comments in rte_eth_dev_data
>   - improve doxygen of rte_eth_dev_release_port()
>   - fix data freeing in some drivers
> 
> Changes in v4:
>   - do not free data fields which are not dynamically allocated blocks
>   - remove rte_eth_dev_release_port_secondary()
>   - remove testpmd check to detach without closing
> 
> Changes in v3:
>   - free queues, MAC addresses and private structure
>     in rte_eth_dev_release_port.
> 
> 
> Thomas Monjalon (5):
>   app/testpmd: allow detaching a port not closed
>   ethdev: fix doxygen comments of shared data fields
>   ethdev: free all common data when releasing port
>   ethdev: remove release function for secondary process
>   ethdev: complete closing of port
> 
> Wisam Jaddo (1):
>   app/testpmd: update port list for multiple removals

Series applied to dpdk-next-net/master, thanks.

^ permalink raw reply	[flat|nested] 78+ messages in thread

end of thread, other threads:[~2018-10-22 15:43 UTC | newest]

Thread overview: 78+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-07 23:39 [dpdk-dev] [RFC] ethdev: complete closing to free all resources Thomas Monjalon
2018-09-10  8:03 ` Andrew Rybchenko
2018-09-10  8:42   ` Thomas Monjalon
2018-09-10  8:54     ` Andrew Rybchenko
2018-09-12 14:57       ` Thomas Monjalon
2018-09-12 15:44         ` Andrew Rybchenko
2018-09-28 12:46 ` Ferruh Yigit
2018-10-09 22:00   ` Thomas Monjalon
2018-10-09 22:17 ` [dpdk-dev] [PATCH v2] ethdev: complete closing of port Thomas Monjalon
2018-10-10  6:15   ` Andrew Rybchenko
2018-10-10  7:44     ` Thomas Monjalon
2018-10-10  7:50       ` Andrew Rybchenko
2018-10-10  8:39         ` Thomas Monjalon
2018-10-10 15:01           ` Andrew Rybchenko
2018-10-10 16:43             ` Thomas Monjalon
2018-10-10 18:01               ` Andrew Rybchenko
2018-10-10 19:03                 ` Thomas Monjalon
2018-10-14 23:20 ` [dpdk-dev] [PATCH v3 0/2] ethdev port freeing Thomas Monjalon
2018-10-14 23:20   ` [dpdk-dev] [PATCH v3 1/2] ethdev: free all common data when releasing port Thomas Monjalon
2018-10-16 11:16     ` Andrew Rybchenko
2018-10-16 12:22       ` Thomas Monjalon
2018-10-16 12:47         ` Andrew Rybchenko
2018-10-16 12:52           ` Thomas Monjalon
2018-10-16 12:55             ` Andrew Rybchenko
2018-10-14 23:20   ` [dpdk-dev] [PATCH v3 2/2] ethdev: complete closing of port Thomas Monjalon
2018-10-16 11:24     ` Andrew Rybchenko
2018-10-16 12:25       ` Thomas Monjalon
2018-10-17  1:54 ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Thomas Monjalon
2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 1/4] app/testpmd: allow detaching a port not closed Thomas Monjalon
2018-10-17  2:06     ` Thomas Monjalon
2018-10-17  6:26     ` Andrew Rybchenko
2018-10-17  8:20       ` Thomas Monjalon
2018-10-17 10:30         ` Iremonger, Bernard
2018-10-17 11:33           ` Thomas Monjalon
2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 2/4] ethdev: free all common data when releasing port Thomas Monjalon
2018-10-17  7:13     ` Andrew Rybchenko
2018-10-17  8:22       ` Thomas Monjalon
2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 3/4] ethdev: remove release function for secondary process Thomas Monjalon
2018-10-17  7:25     ` Andrew Rybchenko
2018-10-17  9:27       ` Thomas Monjalon
2018-10-17  1:54   ` [dpdk-dev] [PATCH v3 4/4] ethdev: complete closing of port Thomas Monjalon
2018-10-17  2:12     ` Thomas Monjalon
2018-10-17 10:24   ` [dpdk-dev] [PATCH v3 0/4] ethdev port freeing Shreyansh Jain
2018-10-17 11:31     ` Thomas Monjalon
2018-10-18  1:23 ` [dpdk-dev] [PATCH v5 0/6] " Thomas Monjalon
2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 1/6] app/testpmd: fix ports list after removing several at once Thomas Monjalon
2018-10-18 10:40     ` Iremonger, Bernard
2018-10-18 11:29       ` Thomas Monjalon
2018-10-18 11:41         ` Iremonger, Bernard
2018-10-18 14:21           ` Thomas Monjalon
2018-10-18 16:42             ` Iremonger, Bernard
2018-10-18 17:06               ` Thomas Monjalon
2018-10-18 11:49         ` Wisam Monther
2018-10-18 13:22           ` Iremonger, Bernard
2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 2/6] app/testpmd: allow detaching a port not closed Thomas Monjalon
2018-10-18  7:45     ` Andrew Rybchenko
2018-10-18 10:51       ` Iremonger, Bernard
2018-10-18 11:24         ` Thomas Monjalon
2018-10-18  1:23   ` [dpdk-dev] [PATCH v5 3/6] ethdev: fix doxygen comments of shared data fields Thomas Monjalon
2018-10-18  7:11     ` Andrew Rybchenko
2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 4/6] ethdev: free all common data when releasing port Thomas Monjalon
2018-10-18  7:13     ` Andrew Rybchenko
2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 5/6] ethdev: remove release function for secondary process Thomas Monjalon
2018-10-18  7:15     ` Andrew Rybchenko
2018-10-18  1:24   ` [dpdk-dev] [PATCH v5 6/6] ethdev: complete closing of port Thomas Monjalon
2018-10-18  8:33     ` Andrew Rybchenko
2018-10-18  9:32       ` Thomas Monjalon
2018-10-19  2:07 ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Thomas Monjalon
2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 1/6] app/testpmd: update port list for multiple removals Thomas Monjalon
2018-10-19 14:32     ` Iremonger, Bernard
2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 2/6] app/testpmd: allow detaching a port not closed Thomas Monjalon
2018-10-19 14:32     ` Iremonger, Bernard
2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 3/6] ethdev: fix doxygen comments of shared data fields Thomas Monjalon
2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 4/6] ethdev: free all common data when releasing port Thomas Monjalon
2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 5/6] ethdev: remove release function for secondary process Thomas Monjalon
2018-10-19  2:07   ` [dpdk-dev] [PATCH v6 6/6] ethdev: complete closing of port Thomas Monjalon
2018-10-19 10:13     ` Andrew Rybchenko
2018-10-22 15:43   ` [dpdk-dev] [PATCH v6 0/6] ethdev port freeing Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).