[dpdk-dev,v1,28/28] ether: support SoC device/driver

Message ID 1462542490-15556-29-git-send-email-viktorin@rehivetech.com (mailing list archive)
State Changes Requested, archived
Headers

Commit Message

Jan Viktorin May 6, 2016, 1:48 p.m. UTC
  Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
---
 lib/librte_ether/rte_ethdev.c | 127 +++++++++++++++++++++++++++++++++++++++++-
 lib/librte_ether/rte_ethdev.h |  31 +++++++++++
 2 files changed, 157 insertions(+), 1 deletion(-)
  

Comments

Shreyansh Jain June 29, 2016, 9:42 a.m. UTC | #1
Hi Jan,

On Friday 06 May 2016 07:18 PM, Jan Viktorin wrote:
> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
> ---
>  lib/librte_ether/rte_ethdev.c | 127 +++++++++++++++++++++++++++++++++++++++++-
>  lib/librte_ether/rte_ethdev.h |  31 +++++++++++
>  2 files changed, 157 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index 4af2e5f..9259c2c 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -320,6 +320,99 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
>  }
>  
[...]
> +int
>  rte_eth_dev_is_valid_port(uint8_t port_id)
>  {
>  	if (port_id >= RTE_MAX_ETHPORTS ||
> @@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
>  
>  	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
>  	(*dev->dev_ops->dev_infos_get)(dev, dev_info);
> -	dev_info->pci_dev = dev->pci_dev;
> +	dev_info->soc_dev = dev->soc_dev;

I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?

>  	dev_info->driver_name = dev->data->drv_name;
>  }
>  
[...]

-
Shreyansh
  
Jan Viktorin July 4, 2016, 1:04 p.m. UTC | #2
On Wed, 29 Jun 2016 15:12:07 +0530
Shreyansh jain <shreyansh.jain@nxp.com> wrote:

> Hi Jan,
> 
> On Friday 06 May 2016 07:18 PM, Jan Viktorin wrote:
> > Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
> > ---
> >  lib/librte_ether/rte_ethdev.c | 127 +++++++++++++++++++++++++++++++++++++++++-
> >  lib/librte_ether/rte_ethdev.h |  31 +++++++++++
> >  2 files changed, 157 insertions(+), 1 deletion(-)
> > 
> > diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> > index 4af2e5f..9259c2c 100644
> > --- a/lib/librte_ether/rte_ethdev.c
> > +++ b/lib/librte_ether/rte_ethdev.c
> > @@ -320,6 +320,99 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
> >  }
> >    
> [...]
> > +int
> >  rte_eth_dev_is_valid_port(uint8_t port_id)
> >  {
> >  	if (port_id >= RTE_MAX_ETHPORTS ||
> > @@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
> >  
> >  	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
> >  	(*dev->dev_ops->dev_infos_get)(dev, dev_info);
> > -	dev_info->pci_dev = dev->pci_dev;
> > +	dev_info->soc_dev = dev->soc_dev;  
> 
> I think both the members, pci_dev and soc_dev, should be updated by this call.
> Is there some specific reason why soc_dev is the only one which is getting updated?

Yes, looks like a mistake. Thanks! And sorry for delayed reply.

Jan

> 
> >  	dev_info->driver_name = dev->data->drv_name;
> >  }
> >    
> [...]
> 
> -
> Shreyansh
>
  
Shreyansh Jain July 4, 2016, 2:27 p.m. UTC | #3
On Monday 04 July 2016 06:34 PM, Jan Viktorin wrote:
> On Wed, 29 Jun 2016 15:12:07 +0530
> Shreyansh jain <shreyansh.jain@nxp.com> wrote:
> 
>> Hi Jan,
>>
>> On Friday 06 May 2016 07:18 PM, Jan Viktorin wrote:
>>> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
>>> ---
>>>  lib/librte_ether/rte_ethdev.c | 127 +++++++++++++++++++++++++++++++++++++++++-
>>>  lib/librte_ether/rte_ethdev.h |  31 +++++++++++
>>>  2 files changed, 157 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
>>> index 4af2e5f..9259c2c 100644
>>> --- a/lib/librte_ether/rte_ethdev.c
>>> +++ b/lib/librte_ether/rte_ethdev.c
>>> @@ -320,6 +320,99 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
>>>  }
>>>    
>> [...]
>>> +int
>>>  rte_eth_dev_is_valid_port(uint8_t port_id)
>>>  {
>>>  	if (port_id >= RTE_MAX_ETHPORTS ||
>>> @@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
>>>  
>>>  	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
>>>  	(*dev->dev_ops->dev_infos_get)(dev, dev_info);
>>> -	dev_info->pci_dev = dev->pci_dev;
>>> +	dev_info->soc_dev = dev->soc_dev;  
>>
>> I think both the members, pci_dev and soc_dev, should be updated by this call.
>> Is there some specific reason why soc_dev is the only one which is getting updated?
> 
> Yes, looks like a mistake. Thanks! And sorry for delayed reply.

No problems - thanks for confirmation.
I have gone through almost complete series and as and when you rebase it, it would have my ACK.
rte_driver patchset which I sent last are broken - I will publish an updated version very soon.

> 
> Jan
> 
>>
>>>  	dev_info->driver_name = dev->data->drv_name;
>>>  }
>>>    
>> [...]
>>
>> -
>> Shreyansh
>>
> 
> 
> 

-
Shreyansh
  
Jan Viktorin July 4, 2016, 2:36 p.m. UTC | #4
On Mon, 4 Jul 2016 19:57:18 +0530
Shreyansh jain <shreyansh.jain@nxp.com> wrote:

[...]

> >>> @@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
> >>>  
> >>>  	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
> >>>  	(*dev->dev_ops->dev_infos_get)(dev, dev_info);
> >>> -	dev_info->pci_dev = dev->pci_dev;
> >>> +	dev_info->soc_dev = dev->soc_dev;    
> >>
> >> I think both the members, pci_dev and soc_dev, should be updated by this call.
> >> Is there some specific reason why soc_dev is the only one which is getting updated?  
> > 
> > Yes, looks like a mistake. Thanks! And sorry for delayed reply.  
> 
> No problems - thanks for confirmation.
> I have gone through almost complete series and as and when you rebase it, it would have my ACK.

OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
be some more tests in my v2.

> rte_driver patchset which I sent last are broken - I will publish an updated version very soon.

I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...

Jan
  
Shreyansh Jain July 5, 2016, 4:42 a.m. UTC | #5
On Monday 04 July 2016 08:06 PM, Jan Viktorin wrote:
> On Mon, 4 Jul 2016 19:57:18 +0530
> Shreyansh jain <shreyansh.jain@nxp.com> wrote:
> 
> [...]
> 
>>>>> @@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
>>>>>  
>>>>>  	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
>>>>>  	(*dev->dev_ops->dev_infos_get)(dev, dev_info);
>>>>> -	dev_info->pci_dev = dev->pci_dev;
>>>>> +	dev_info->soc_dev = dev->soc_dev;    
>>>>
>>>> I think both the members, pci_dev and soc_dev, should be updated by this call.
>>>> Is there some specific reason why soc_dev is the only one which is getting updated?  
>>>
>>> Yes, looks like a mistake. Thanks! And sorry for delayed reply.  
>>
>> No problems - thanks for confirmation.
>> I have gone through almost complete series and as and when you rebase it, it would have my ACK.
> 
> OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
> be some more tests in my v2.
> 
>> rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
> 
> I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
> I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...

Really? Then probably I understood it wrong. I don't have any issues with the first one as well but just for slightly cleaner approach I thought of going with your suggest (or, suggestion as understood by me).

Anyways the patch is broken and doesn't apply on master. I will push a new version (with revert EAL_PCI_REGISTER arguments) within today.

> 
> Jan
> 

-
Shreyansh
  
Jan Viktorin July 5, 2016, 5:16 a.m. UTC | #6
Hello Shreyansh,
‎
> On Monday 04 July 2016 08:06 PM, Jan Viktorin wrote:
>> On Mon, 4 Jul 2016 19:57:18 +0530
>> Shreyansh jain <shreyansh.jain@nxp.com> wrote:
>> 
>> [...]
>> 
>>>>>> @@ -1431,7 +1524,7 @@ >rte_eth_dev_info_get(uint8_t port_id, struct >rte_eth_dev_info *dev_info)
>>>>>> 
>>>>>> RTE_FUNC_PTR_OR_RET(*dev->dev_ops->>dev_infos_get);
>>>>>> (*dev->dev_ops->dev_infos_get)(dev, dev_info);
>>>>>> -	dev_info->pci_dev = dev->pci_dev;
>>>>>> +	dev_info->soc_dev = dev->soc_dev; 
>>>>>
>>>>> I think both the members, pci_dev and soc_dev, should be updated by this call.
>>>>> Is there some specific reason why soc_dev is the only one which is getting updated? 
>>>>
>>>> Yes, looks like a mistake. Thanks! And sorry for delayed reply. 
>>>
>>> No problems - thanks for confirmation.
>>> I have gone through almost complete series and as and when you rebase it, it would have my ACK.
>> 
>> OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
>> be some more tests in my v2.
>> 
>>> rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
>> 
>> I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
>> I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...
>
> Really? Then probably I understood it wrong. I don't have any issues with the first one as well but just for slightly cleaner approach I thought of going with your suggest (or, suggestion as understood by me).
‎>
> Anyways the patch is broken and doesn't apply on master. I will push a new version (with revert EAL_PCI_REGISTER arguments) within today.

Ok. I am away for few days this week but I will continue as soon as possible on the soc patchset and also on the rte_device/driver issue. We have to cut this as soon as possible. I think the best would be to post a small patchset on top of this one introducing the change.

I think, there should be a single list of rte_device and a list for rte_driver while preserving lists for each infra, so also rte_pci_device would have a separate list. Then, it's possible to iterate over all PCI devices easily and iterate over all devices generically at the same time.

What I am not sure about are addr and id things. It's quite difficult to generalize them. The addr needs a conpare function but how to compare pci addr to another type of addr? Do we need this? If so, I'll work on this.

Another thing - resources. Do we want to have a kind of a generic rte_resource instead of rte_pci_resource? I think this is clearly possible. I am about to do this.

I am afraid we are unable to change devargs significantly in this release :/ (due to time and lack of a discussion here).‎ What I really like to see is the virtual device conversion and pmd_type removal. Are you able to look at this?

Any other objections?

Jan Viktorin
RehiveTech
Sent from a mobile device‎

>> 
>> Jan
>> 
>
>-
>Shreyansh
  
Shreyansh Jain July 7, 2016, 10:29 a.m. UTC | #7
Hi Jan,

Apologies for delay in my response.

On Tuesday 05 July 2016 10:46 AM, Jan Viktorin wrote:
> Hello Shreyansh,
> ‎
>> On Monday 04 July 2016 08:06 PM, Jan Viktorin wrote:
>>> On Mon, 4 Jul 2016 19:57:18 +0530
>>> Shreyansh jain <shreyansh.jain@nxp.com> wrote:
>>>
>>> [...]
>>>
>>>>>>> @@ -1431,7 +1524,7 @@ >rte_eth_dev_info_get(uint8_t port_id, struct >rte_eth_dev_info *dev_info)
>>>>>>>
>>>>>>> RTE_FUNC_PTR_OR_RET(*dev->dev_ops->>dev_infos_get);
>>>>>>> (*dev->dev_ops->dev_infos_get)(dev, dev_info);
>>>>>>> -	dev_info->pci_dev = dev->pci_dev;
>>>>>>> +	dev_info->soc_dev = dev->soc_dev; 
>>>>>>
>>>>>> I think both the members, pci_dev and soc_dev, should be updated by this call.
>>>>>> Is there some specific reason why soc_dev is the only one which is getting updated? 
>>>>>
>>>>> Yes, looks like a mistake. Thanks! And sorry for delayed reply. 
>>>>
>>>> No problems - thanks for confirmation.
>>>> I have gone through almost complete series and as and when you rebase it, it would have my ACK.
>>>
>>> OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
>>> be some more tests in my v2.
>>>
>>>> rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
>>>
>>> I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
>>> I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...
>>
>> Really? Then probably I understood it wrong. I don't have any issues with the first one as well but just for slightly cleaner approach I thought of going with your suggest (or, suggestion as understood by me).
> ‎>
>> Anyways the patch is broken and doesn't apply on master. I will push a new version (with revert EAL_PCI_REGISTER arguments) within today.
> 
> Ok. I am away for few days this week but I will continue as soon as possible on the soc patchset and also on the rte_device/driver issue. We have to cut this as soon as possible. I think the best would be to post a small patchset on top of this one introducing the change.

I am anyway working on a driver for NXP's SoC platform which I am basing over rte_device + SoC patchset.
I plan to release a draft of this driver soon. It might help validate both the patchsets in a limited manner.

> 
> I think, there should be a single list of rte_device and a list for rte_driver while preserving lists for each infra, so also rte_pci_device would have a separate list. Then, it's possible to iterate over all PCI devices easily and iterate over all devices generically at the same time.

I have similar understanding. Separate pci/soc lists, and unified rte_driver and rte_device lists. This, in my opinion, would help keep the interfaces clean (free of unnecessary checks).

> 
> What I am not sure about are addr and id things. It's quite difficult to generalize them. The addr needs a conpare function but how to compare pci addr to another type of addr? Do we need this? If so, I'll work on this.

I am not sure why we need to compare the PCI addresses with non-PCI (or any other, SoC) address set? Can you elaborate?

> 
> Another thing - resources. Do we want to have a kind of a generic rte_resource instead of rte_pci_resource? I think this is clearly possible. I am about to do this.

The idea sounds good but I don't know whether it would be feasible or not. My understanding is that resources have special characteristics. Generalizing them would involve creating opaque objects in rte_resource{..} which in turn beats the purpose of generalization.

Probably, I will wait for your next patchset version to understand your approach.

> 
> I am afraid we are unable to change devargs significantly in this release :/ (due to time and lack of a discussion here).‎ What I really like to see is the virtual device conversion and pmd_type removal. Are you able to look at this?

pmd_type removal is my todo as well. This would anyway impact the vdevs.
I haven't given devargs much thought, yet.

> 
> Any other objections?

I was looking at various discussions [1],[2] that have happened in past. From that, the summary I have is:
 1) Generalize devices to rte_device/rte_driver
  `-- Cleaner interfaces/difference for 'bus', 'driver' and 'device'
  `-- Moving the init/deinit functions into rte_device/rte_driver layer
  `-- hierarchical device structure (as explained by David in [1]) 
 2) Do away with device type specific initializations (registrations)
  `-- No more pdev/vdev distinction
  `-- standardizing devargs for accepting device specific strings.
 3) Hotplug support

Most of work of (1) David has already done. What remains is completing (2) and probably (3) which I haven't verified yet.

[1] http://dpdk.org/ml/archives/dev/2016-January/031390.html
[2] http://dpdk.org/ml/archives/dev/2016-January/030975.html

> 
> Jan Viktorin
> RehiveTech
> Sent from a mobile device‎
> 
>>>
>>> Jan
>>>  
>>
>> -
>> Shreyansh
> 

-
Shreyansh
  
Shreyansh Jain July 12, 2016, 8:45 a.m. UTC | #8
Hi Jan,

On Monday 04 July 2016 08:06 PM, Jan Viktorin wrote:
> On Mon, 4 Jul 2016 19:57:18 +0530
> Shreyansh jain <shreyansh.jain@nxp.com> wrote:
> 
> [...]
> 
>>>>> @@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
>>>>>  
>>>>>  	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
>>>>>  	(*dev->dev_ops->dev_infos_get)(dev, dev_info);
>>>>> -	dev_info->pci_dev = dev->pci_dev;
>>>>> +	dev_info->soc_dev = dev->soc_dev;    
>>>>
>>>> I think both the members, pci_dev and soc_dev, should be updated by this call.
>>>> Is there some specific reason why soc_dev is the only one which is getting updated?  
>>>
>>> Yes, looks like a mistake. Thanks! And sorry for delayed reply.  
>>
>> No problems - thanks for confirmation.
>> I have gone through almost complete series and as and when you rebase it, it would have my ACK.
> 
> OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
> be some more tests in my v2.
> 
>> rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
> 
> I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
> I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...

I have sent across a v6 of the rte_device/driver change set.
Can you see if that is in-line with your expectations as well as the series [1] posted by you recently?
I was making changes for vdev but for now I have ignored them as your series already includes those changes.

I used your patches and based them over the v6 rte_device patchset - besides some minor conflicts, its seems to merge fine.

[1] http://dpdk.org/ml/archives/dev/2016-July/043645.html

> 
> Jan
> 

-
Shreyansh
  
Jan Viktorin July 12, 2016, 10:41 a.m. UTC | #9
On Tue, 12 Jul 2016 14:15:17 +0530
Shreyansh jain <shreyansh.jain@nxp.com> wrote:

> Hi Jan,
> 
> On Monday 04 July 2016 08:06 PM, Jan Viktorin wrote:
> > On Mon, 4 Jul 2016 19:57:18 +0530
> > Shreyansh jain <shreyansh.jain@nxp.com> wrote:
> > 
> > [...]
> >   
> >>>>> @@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
> >>>>>  
> >>>>>  	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
> >>>>>  	(*dev->dev_ops->dev_infos_get)(dev, dev_info);
> >>>>> -	dev_info->pci_dev = dev->pci_dev;
> >>>>> +	dev_info->soc_dev = dev->soc_dev;      
> >>>>
> >>>> I think both the members, pci_dev and soc_dev, should be updated by this call.
> >>>> Is there some specific reason why soc_dev is the only one which is getting updated?    
> >>>
> >>> Yes, looks like a mistake. Thanks! And sorry for delayed reply.    
> >>
> >> No problems - thanks for confirmation.
> >> I have gone through almost complete series and as and when you rebase it, it would have my ACK.  
> > 
> > OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
> > be some more tests in my v2.
> >   
> >> rte_driver patchset which I sent last are broken - I will publish an updated version very soon.  
> > 
> > I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
> > I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...  
> 
> I have sent across a v6 of the rte_device/driver change set.
> Can you see if that is in-line with your expectations as well as the series [1] posted by you recently?
> I was making changes for vdev but for now I have ignored them as your series already includes those changes.
> 
> I used your patches and based them over the v6 rte_device patchset - besides some minor conflicts, its seems to merge fine.
> 
> [1] http://dpdk.org/ml/archives/dev/2016-July/043645.html

I will check it as soon as possible. Thanks.

Jan

> 
> > 
> > Jan
> >   
> 
> -
> Shreyansh
>
  

Patch

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 4af2e5f..9259c2c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -320,6 +320,99 @@  rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
 }
 
 int
+rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+		      struct rte_soc_device *soc_dev)
+{
+	struct eth_driver    *eth_drv;
+	struct rte_eth_dev *eth_dev;
+	char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+
+	int diag;
+
+	eth_drv = container_of(soc_drv, struct eth_driver, soc_drv);
+
+	rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+			sizeof(ethdev_name));
+
+	eth_dev = rte_eth_dev_allocate(ethdev_name);
+	if (eth_dev == NULL)
+		return -ENOMEM;
+
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		eth_dev->data->dev_private = rte_zmalloc("ethdev private structure",
+				  eth_drv->dev_private_size,
+				  RTE_CACHE_LINE_SIZE);
+		if (eth_dev->data->dev_private == NULL)
+			rte_panic("Cannot allocate memzone for private port data\n");
+	}
+	eth_dev->soc_dev = soc_dev;
+	eth_dev->driver = eth_drv;
+	eth_dev->data->rx_mbuf_alloc_failed = 0;
+
+	/* init user callbacks */
+	TAILQ_INIT(&(eth_dev->link_intr_cbs));
+
+	/*
+	 * Set the default MTU.
+	 */
+	eth_dev->data->mtu = ETHER_MTU;
+
+	/* Invoke PMD device initialization function */
+	diag = (*eth_drv->eth_dev_init)(eth_dev);
+	if (diag == 0)
+		return 0;
+
+	RTE_PMD_DEBUG_TRACE("driver %s: eth_dev_init(%s) failed\n",
+			soc_drv->name,
+			soc_dev->id.name);
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		rte_free(eth_dev->data->dev_private);
+	rte_eth_dev_release_port(eth_dev);
+	return diag;
+}
+
+int
+rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev)
+{
+	const struct eth_driver *eth_drv;
+	struct rte_eth_dev *eth_dev;
+	char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+	int ret;
+
+	if (soc_dev == NULL)
+		return -EINVAL;
+
+	rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+			sizeof(ethdev_name));
+
+	eth_dev = rte_eth_dev_allocated(ethdev_name);
+	if (eth_dev == NULL)
+		return -ENODEV;
+
+	eth_drv = container_of(soc_dev->driver, struct eth_driver, soc_drv);
+
+	/* Invoke PMD device uninit function */
+	if (*eth_drv->eth_dev_uninit) {
+		ret = (*eth_drv->eth_dev_uninit)(eth_dev);
+		if (ret)
+			return ret;
+	}
+
+	/* 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->soc_dev = NULL;
+	eth_dev->driver = NULL;
+	eth_dev->data = NULL;
+
+	return 0;
+}
+
+
+int
 rte_eth_dev_is_valid_port(uint8_t port_id)
 {
 	if (port_id >= RTE_MAX_ETHPORTS ||
@@ -1431,7 +1524,7 @@  rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
 
 	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
 	(*dev->dev_ops->dev_infos_get)(dev, dev_info);
-	dev_info->pci_dev = dev->pci_dev;
+	dev_info->soc_dev = dev->soc_dev;
 	dev_info->driver_name = dev->data->drv_name;
 }
 
@@ -2408,8 +2501,13 @@  static inline
 struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev)
 {
 	if (dev->pci_dev) {
+		RTE_VERIFY(dev->soc_dev == NULL);
 		return &dev->pci_dev->intr_handle;
 	}
+	if (dev->soc_dev) {
+		RTE_VERIFY(dev->pci_dev == NULL);
+		return &dev->soc_dev->intr_handle;
+	}
 
 	RTE_VERIFY(0);
 	return NULL;
@@ -2453,8 +2551,13 @@  static inline
 const char *eth_dev_get_driver_name(const struct rte_eth_dev *dev)
 {
 	if (dev->pci_dev) {
+		RTE_VERIFY(dev->soc_dev == NULL);
 		return dev->driver->pci_drv.name;
 	}
+	if (dev->soc_dev) {
+		RTE_VERIFY(dev->pci_dev == NULL);
+		return dev->driver->soc_drv.name;
+	}
 
 	RTE_VERIFY(0);
 	return NULL;
@@ -3114,6 +3217,28 @@  rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
 	eth_dev->data->drv_name = pci_dev->driver->name;
 }
 
+void
+rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev, struct rte_soc_device *soc_dev)
+{
+	if ((eth_dev == NULL) || (soc_dev == NULL)) {
+		RTE_PMD_DEBUG_TRACE("NULL pointer eth_dev=%p soc_dev=%p\n",
+				eth_dev, soc_dev);
+		return;
+	}
+
+	RTE_VERIFY(eth_dev->soc_dev != NULL);
+
+	eth_dev->data->dev_flags = 0;
+	if (soc_dev->driver->drv_flags & RTE_SOC_DRV_INTR_LSC)
+		eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
+	if (soc_dev->driver->drv_flags & RTE_SOC_DRV_DETACHABLE)
+		eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
+
+	eth_dev->data->kdrv = soc_dev->kdrv;
+	eth_dev->data->numa_node = soc_dev->numa_node;
+	eth_dev->data->drv_name = soc_dev->driver->name;
+}
+
 int
 rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
 				    struct rte_eth_l2_tunnel_conf *l2_tunnel)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 622c9d8..9ecc3b8 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -180,6 +180,7 @@  extern "C" {
 #include <rte_log.h>
 #include <rte_interrupts.h>
 #include <rte_pci.h>
+#include <rte_soc.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
 #include "rte_ether.h"
@@ -855,6 +856,7 @@  struct rte_eth_conf {
  */
 struct rte_eth_dev_info {
 	struct rte_pci_device *pci_dev; /**< Device PCI information. */
+	struct rte_soc_device *soc_dev; /**< Device SoC information. */
 	const char *driver_name; /**< Device Driver name. */
 	unsigned int if_index; /**< Index to bound host interface, or 0 if none.
 		Use if_indextoname() to translate into an interface name. */
@@ -1590,6 +1592,7 @@  struct rte_eth_dev {
 	const struct eth_driver *driver;/**< Driver for this device */
 	const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */
 	struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */
+	struct rte_soc_device *soc_dev; /**< SoC info. supplied by probing */
 	/** User application callbacks for NIC interrupts */
 	struct rte_eth_dev_cb_list link_intr_cbs;
 	/**
@@ -1823,6 +1826,7 @@  typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
  */
 struct eth_driver {
 	struct rte_pci_driver pci_drv;    /**< The PMD is also a PCI driver. */
+	struct rte_soc_driver soc_drv;    /**< The PMD is also a SoC driver. */
 	eth_dev_init_t eth_dev_init;      /**< Device init function. */
 	eth_dev_uninit_t eth_dev_uninit;  /**< Device uninit function. */
 	unsigned int dev_private_size;    /**< Size of device private data. */
@@ -4158,6 +4162,20 @@  void rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev,
 		struct rte_pci_device *pci_dev);
 
 /**
+ * Copy SoC device info to the Ethernet device data.
+ *
+ * @param eth_dev
+ * The *eth_dev* pointer is the address of the *rte_eth_dev* structure.
+ * @param soc_dev
+ * The *soc_dev* pointer is the address of the *rte_soc_device* structure.
+ *
+ * @return
+ *   - 0 on success, negative on error
+ */
+void rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev,
+		struct rte_soc_device *soc_dev);
+
+/**
  * Create memzone for HW rings.
  * malloc can't be used as the physical address is needed.
  * If the memzone is already created, then this function returns a ptr
@@ -4241,6 +4259,19 @@  int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
  */
 int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev);
 
+/**
+ * Wrapper for use by SoC drivers as a .devinit function to attach to a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+			  struct rte_soc_device *soc_dev);
+
+/**
+ * Wrapper for use by SoC drivers as a .devuninit function to detach a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev);
+
 #ifdef __cplusplus
 }
 #endif