[dpdk-dev] pci: Add the class_id support in pci probe

Message ID 1451357606-117892-1-git-send-email-ziye.yang@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers

Commit Message

Ziye Yang Dec. 29, 2015, 2:53 a.m. UTC
  This patch is used to add the class_id support
for pci_probe since some devices need the class_info
(class_code, subclass_code, programming_interface)

Signed-off-by: Ziye Yang <ziye.yang@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c     | 4 ++++
 lib/librte_eal/common/eal_common_pci.c  | 3 +++
 lib/librte_eal/common/include/rte_pci.h | 8 ++++++--
 lib/librte_eal/linuxapp/eal/eal_pci.c   | 9 +++++++++
 4 files changed, 22 insertions(+), 2 deletions(-)
  

Comments

Stephen Hemminger Dec. 31, 2015, 5:12 p.m. UTC | #1
On Tue, 29 Dec 2015 10:53:26 +0800
Ziye Yang <ziye.yang@intel.com> wrote:

> This patch is used to add the class_id support
> for pci_probe since some devices need the class_info
> (class_code, subclass_code, programming_interface)
> 
> Signed-off-by: Ziye Yang <ziye.yang@intel.com>

Since rte_pci is exposed to application this breaks the ABI.
  
Bruce Richardson Jan. 13, 2016, 11:55 a.m. UTC | #2
On Thu, Dec 31, 2015 at 09:12:14AM -0800, Stephen Hemminger wrote:
> On Tue, 29 Dec 2015 10:53:26 +0800
> Ziye Yang <ziye.yang@intel.com> wrote:
> 
> > This patch is used to add the class_id support
> > for pci_probe since some devices need the class_info
> > (class_code, subclass_code, programming_interface)
> > 
> > Signed-off-by: Ziye Yang <ziye.yang@intel.com>
> 
> Since rte_pci is exposed to application this breaks the ABI.

But applications are not going to be defining rte_pci_ids values internally, are
they? That is for drivers to use. Is this really an ABI breakage for applications that we
need to be concerned about?

/Bruce
  
Panu Matilainen Jan. 13, 2016, 12:22 p.m. UTC | #3
On 01/13/2016 01:55 PM, Bruce Richardson wrote:
> On Thu, Dec 31, 2015 at 09:12:14AM -0800, Stephen Hemminger wrote:
>> On Tue, 29 Dec 2015 10:53:26 +0800
>> Ziye Yang <ziye.yang@intel.com> wrote:
>>
>>> This patch is used to add the class_id support
>>> for pci_probe since some devices need the class_info
>>> (class_code, subclass_code, programming_interface)
>>>
>>> Signed-off-by: Ziye Yang <ziye.yang@intel.com>
>>
>> Since rte_pci is exposed to application this breaks the ABI.
>
> But applications are not going to be defining rte_pci_ids values internally, are
> they? That is for drivers to use. Is this really an ABI breakage for applications that we
> need to be concerned about?

There might not be applications using it but drivers are ABI consumers 
too - think of 3rd party drivers and such.

	- Panu -
  
Thomas Monjalon Jan. 28, 2016, 9:38 p.m. UTC | #4
2016-01-13 14:22, Panu Matilainen:
> On 01/13/2016 01:55 PM, Bruce Richardson wrote:
> > On Thu, Dec 31, 2015 at 09:12:14AM -0800, Stephen Hemminger wrote:
> >> On Tue, 29 Dec 2015 10:53:26 +0800
> >> Ziye Yang <ziye.yang@intel.com> wrote:
> >>
> >>> This patch is used to add the class_id support
> >>> for pci_probe since some devices need the class_info
> >>> (class_code, subclass_code, programming_interface)
> >>>
> >>> Signed-off-by: Ziye Yang <ziye.yang@intel.com>
> >>
> >> Since rte_pci is exposed to application this breaks the ABI.
> >
> > But applications are not going to be defining rte_pci_ids values internally, are
> > they? That is for drivers to use. Is this really an ABI breakage for applications that we
> > need to be concerned about?
> 
> There might not be applications using it but drivers are ABI consumers 
> too - think of 3rd party drivers and such.

Drivers are not ABI consumers in the sense that ABI means
Application Binary Interface.
We are talking about drivers interface here.
When establishing the ABI policy we were discussing about applications only.

I agree we must allow 3rd party drivers but there is no good reason
to try to upgrade DPDK without upgrading/porting the external drivers.
If someone does not want to release its driver and keep upgrading DPDK,
it is acceptable IMHO to force an upgrade of its driver.
  
Panu Matilainen Jan. 29, 2016, 9:21 a.m. UTC | #5
On 01/28/2016 11:38 PM, Thomas Monjalon wrote:
> 2016-01-13 14:22, Panu Matilainen:
>> On 01/13/2016 01:55 PM, Bruce Richardson wrote:
>>> On Thu, Dec 31, 2015 at 09:12:14AM -0800, Stephen Hemminger wrote:
>>>> On Tue, 29 Dec 2015 10:53:26 +0800
>>>> Ziye Yang <ziye.yang@intel.com> wrote:
>>>>
>>>>> This patch is used to add the class_id support
>>>>> for pci_probe since some devices need the class_info
>>>>> (class_code, subclass_code, programming_interface)
>>>>>
>>>>> Signed-off-by: Ziye Yang <ziye.yang@intel.com>
>>>>
>>>> Since rte_pci is exposed to application this breaks the ABI.
>>>
>>> But applications are not going to be defining rte_pci_ids values internally, are
>>> they? That is for drivers to use. Is this really an ABI breakage for applications that we
>>> need to be concerned about?
>>
>> There might not be applications using it but drivers are ABI consumers
>> too - think of 3rd party drivers and such.
>
> Drivers are not ABI consumers in the sense that ABI means
> Application Binary Interface.
> We are talking about drivers interface here.
> When establishing the ABI policy we were discussing about applications only.

Generally speaking an ABI is an interface between two program (or 
software if you like) modules, its not specific to "applications". 
Looking at http://dpdk.org/doc/guides/contributing/versioning.html I see 
it does only talk about applications, but an ABI consumer can also be 
another library. A driver calling rte_malloc() is just as much 
librte_eal ABI consumer as anything else.

Now, I understand that drivers use and need interface(s) that 
applications have no use for or simply cannot use, and those interfaces 
could be subject to different policies. As an extreme example, the Linux 
kernel has two isolated ABIs, one is the userland system call interface 
which is guaranteed to stay forever and the other is kernel module 
interface, guarantees nothing at all.

In DPDK the difference is far muddier than that since all the interfaces 
live in common, versioned userland DSOs. So if there are two different 
interfaces following two different policies, it's all the more important 
to clearly document them. One simple way could be using a different 
prefix than rte_.

> I agree we must allow 3rd party drivers but there is no good reason
> to try to upgrade DPDK without upgrading/porting the external drivers.
> If someone does not want to release its driver and keep upgrading DPDK,
> it is acceptable IMHO to force an upgrade of its driver.

Note that I've no particular sympathy for 3rd party drivers as such. 
What I *do* care about is that breakage is made explicit, as in drivers 
built for an incompatible version refuse to load at all, instead of 
silently corrupting memory etc.

	- Panu -
  
Thomas Monjalon Jan. 29, 2016, 9:34 a.m. UTC | #6
2016-01-29 11:21, Panu Matilainen:
> On 01/28/2016 11:38 PM, Thomas Monjalon wrote:
> > 2016-01-13 14:22, Panu Matilainen:
> >> On 01/13/2016 01:55 PM, Bruce Richardson wrote:
> >>> On Thu, Dec 31, 2015 at 09:12:14AM -0800, Stephen Hemminger wrote:
> >>>> On Tue, 29 Dec 2015 10:53:26 +0800
> >>>> Ziye Yang <ziye.yang@intel.com> wrote:
> >>>>
> >>>>> This patch is used to add the class_id support
> >>>>> for pci_probe since some devices need the class_info
> >>>>> (class_code, subclass_code, programming_interface)
> >>>>>
> >>>>> Signed-off-by: Ziye Yang <ziye.yang@intel.com>
> >>>>
> >>>> Since rte_pci is exposed to application this breaks the ABI.
> >>>
> >>> But applications are not going to be defining rte_pci_ids values internally, are
> >>> they? That is for drivers to use. Is this really an ABI breakage for applications that we
> >>> need to be concerned about?
> >>
> >> There might not be applications using it but drivers are ABI consumers
> >> too - think of 3rd party drivers and such.
> >
> > Drivers are not ABI consumers in the sense that ABI means
> > Application Binary Interface.
> > We are talking about drivers interface here.
> > When establishing the ABI policy we were discussing about applications only.
> 
> Generally speaking an ABI is an interface between two program (or 
> software if you like) modules, its not specific to "applications". 
> Looking at http://dpdk.org/doc/guides/contributing/versioning.html I see 
> it does only talk about applications, but an ABI consumer can also be 
> another library. A driver calling rte_malloc() is just as much 
> librte_eal ABI consumer as anything else.
> 
> Now, I understand that drivers use and need interface(s) that 
> applications have no use for or simply cannot use, and those interfaces 
> could be subject to different policies. As an extreme example, the Linux 
> kernel has two isolated ABIs, one is the userland system call interface 
> which is guaranteed to stay forever and the other is kernel module 
> interface, guarantees nothing at all.
> 
> In DPDK the difference is far muddier than that since all the interfaces 
> live in common, versioned userland DSOs. So if there are two different 
> interfaces following two different policies, it's all the more important 
> to clearly document them. One simple way could be using a different 
> prefix than rte_.

Good suggestion. Or we can simply have different files with a clear notice
in their headers and in the versioning doc.
It was well split in rte_cryptodev_pmd.h

> > I agree we must allow 3rd party drivers but there is no good reason
> > to try to upgrade DPDK without upgrading/porting the external drivers.
> > If someone does not want to release its driver and keep upgrading DPDK,
> > it is acceptable IMHO to force an upgrade of its driver.
> 
> Note that I've no particular sympathy for 3rd party drivers as such. 
> What I *do* care about is that breakage is made explicit, as in drivers 
> built for an incompatible version refuse to load at all, instead of 
> silently corrupting memory etc.

OK I agree.
Anyway the ABI versionning does not cover the structure changes.
What about making a DPDK version check when registering a driver?
So a binary driver would be clearly bound to a DPDK version.
And we should change or remove the .so version which never change for
most of drivers.
  
Panu Matilainen Jan. 29, 2016, 10:10 a.m. UTC | #7
On 01/29/2016 11:34 AM, Thomas Monjalon wrote:
> 2016-01-29 11:21, Panu Matilainen:
>> On 01/28/2016 11:38 PM, Thomas Monjalon wrote:
>>> 2016-01-13 14:22, Panu Matilainen:
>>>> On 01/13/2016 01:55 PM, Bruce Richardson wrote:
>>>>> On Thu, Dec 31, 2015 at 09:12:14AM -0800, Stephen Hemminger wrote:
>>>>>> On Tue, 29 Dec 2015 10:53:26 +0800
>>>>>> Ziye Yang <ziye.yang@intel.com> wrote:
>>>>>>
>>>>>>> This patch is used to add the class_id support
>>>>>>> for pci_probe since some devices need the class_info
>>>>>>> (class_code, subclass_code, programming_interface)
>>>>>>>
>>>>>>> Signed-off-by: Ziye Yang <ziye.yang@intel.com>
>>>>>>
>>>>>> Since rte_pci is exposed to application this breaks the ABI.
>>>>>
>>>>> But applications are not going to be defining rte_pci_ids values internally, are
>>>>> they? That is for drivers to use. Is this really an ABI breakage for applications that we
>>>>> need to be concerned about?
>>>>
>>>> There might not be applications using it but drivers are ABI consumers
>>>> too - think of 3rd party drivers and such.
>>>
>>> Drivers are not ABI consumers in the sense that ABI means
>>> Application Binary Interface.
>>> We are talking about drivers interface here.
>>> When establishing the ABI policy we were discussing about applications only.
>>
>> Generally speaking an ABI is an interface between two program (or
>> software if you like) modules, its not specific to "applications".
>> Looking at http://dpdk.org/doc/guides/contributing/versioning.html I see
>> it does only talk about applications, but an ABI consumer can also be
>> another library. A driver calling rte_malloc() is just as much
>> librte_eal ABI consumer as anything else.
>>
>> Now, I understand that drivers use and need interface(s) that
>> applications have no use for or simply cannot use, and those interfaces
>> could be subject to different policies. As an extreme example, the Linux
>> kernel has two isolated ABIs, one is the userland system call interface
>> which is guaranteed to stay forever and the other is kernel module
>> interface, guarantees nothing at all.
>>
>> In DPDK the difference is far muddier than that since all the interfaces
>> live in common, versioned userland DSOs. So if there are two different
>> interfaces following two different policies, it's all the more important
>> to clearly document them. One simple way could be using a different
>> prefix than rte_.
>
> Good suggestion. Or we can simply have different files with a clear notice
> in their headers and in the versioning doc.
> It was well split in rte_cryptodev_pmd.h

Using separate headers is also good. Optimally both? :)

>>> I agree we must allow 3rd party drivers but there is no good reason
>>> to try to upgrade DPDK without upgrading/porting the external drivers.
>>> If someone does not want to release its driver and keep upgrading DPDK,
>>> it is acceptable IMHO to force an upgrade of its driver.
>>
>> Note that I've no particular sympathy for 3rd party drivers as such.
>> What I *do* care about is that breakage is made explicit, as in drivers
>> built for an incompatible version refuse to load at all, instead of
>> silently corrupting memory etc.
>
> OK I agree.

Cool, the rest is just details then.

> Anyway the ABI versionning does not cover the structure changes.
> What about making a DPDK version check when registering a driver?
> So a binary driver would be clearly bound to a DPDK version.

That's one possibility. Another way to achieve essentially the same is 
to make rte_eal_driver_register() symbol version follow the DPDK 
version, in which case a driver built for another version will fail at 
dlopen() already.

> And we should change or remove the .so version which never change for
> most of drivers.

Yup, so-versioning DSOs which do not offer any ABI is kinda pointless.

	- Panu -
  
Panu Matilainen Jan. 29, 2016, 12:47 p.m. UTC | #8
On 01/29/2016 12:10 PM, Panu Matilainen wrote:
> On 01/29/2016 11:34 AM, Thomas Monjalon wrote:
>> 2016-01-29 11:21, Panu Matilainen:
>>> On 01/28/2016 11:38 PM, Thomas Monjalon wrote:
>>>> 2016-01-13 14:22, Panu Matilainen:
>>>>> On 01/13/2016 01:55 PM, Bruce Richardson wrote:
>>>>>> On Thu, Dec 31, 2015 at 09:12:14AM -0800, Stephen Hemminger wrote:
>>>>>>> On Tue, 29 Dec 2015 10:53:26 +0800
>>>>>>> Ziye Yang <ziye.yang@intel.com> wrote:
>>>>>>>
>>>>>>>> This patch is used to add the class_id support
>>>>>>>> for pci_probe since some devices need the class_info
>>>>>>>> (class_code, subclass_code, programming_interface)
>>>>>>>>
>>>>>>>> Signed-off-by: Ziye Yang <ziye.yang@intel.com>
>>>>>>>
>>>>>>> Since rte_pci is exposed to application this breaks the ABI.
>>>>>>
>>>>>> But applications are not going to be defining rte_pci_ids values
>>>>>> internally, are
>>>>>> they? That is for drivers to use. Is this really an ABI breakage
>>>>>> for applications that we
>>>>>> need to be concerned about?
>>>>>
>>>>> There might not be applications using it but drivers are ABI consumers
>>>>> too - think of 3rd party drivers and such.
>>>>
>>>> Drivers are not ABI consumers in the sense that ABI means
>>>> Application Binary Interface.
>>>> We are talking about drivers interface here.
>>>> When establishing the ABI policy we were discussing about
>>>> applications only.
>>>
>>> Generally speaking an ABI is an interface between two program (or
>>> software if you like) modules, its not specific to "applications".
>>> Looking at http://dpdk.org/doc/guides/contributing/versioning.html I see
>>> it does only talk about applications, but an ABI consumer can also be
>>> another library. A driver calling rte_malloc() is just as much
>>> librte_eal ABI consumer as anything else.
>>>
>>> Now, I understand that drivers use and need interface(s) that
>>> applications have no use for or simply cannot use, and those interfaces
>>> could be subject to different policies. As an extreme example, the Linux
>>> kernel has two isolated ABIs, one is the userland system call interface
>>> which is guaranteed to stay forever and the other is kernel module
>>> interface, guarantees nothing at all.
>>>
>>> In DPDK the difference is far muddier than that since all the interfaces
>>> live in common, versioned userland DSOs. So if there are two different
>>> interfaces following two different policies, it's all the more important
>>> to clearly document them. One simple way could be using a different
>>> prefix than rte_.
>>
>> Good suggestion. Or we can simply have different files with a clear
>> notice
>> in their headers and in the versioning doc.
>> It was well split in rte_cryptodev_pmd.h
>
> Using separate headers is also good. Optimally both? :)
>
>>>> I agree we must allow 3rd party drivers but there is no good reason
>>>> to try to upgrade DPDK without upgrading/porting the external drivers.
>>>> If someone does not want to release its driver and keep upgrading DPDK,
>>>> it is acceptable IMHO to force an upgrade of its driver.
>>>
>>> Note that I've no particular sympathy for 3rd party drivers as such.
>>> What I *do* care about is that breakage is made explicit, as in drivers
>>> built for an incompatible version refuse to load at all, instead of
>>> silently corrupting memory etc.
>>
>> OK I agree.
>
> Cool, the rest is just details then.
>
>> Anyway the ABI versionning does not cover the structure changes.
>> What about making a DPDK version check when registering a driver?
>> So a binary driver would be clearly bound to a DPDK version.
>
> That's one possibility. Another way to achieve essentially the same is
> to make rte_eal_driver_register() symbol version follow the DPDK
> version, in which case a driver built for another version will fail at
> dlopen() already.

Thinking about this a bit more, symbol versioning doesn't cut it because 
its not always used (static linkakage) and I guess we should cover that too.

Another similar possibility that blocks it at dlopen() level is to munge 
the actual function name to carry a version, so it becomes something 
like rte_eal_driver_register_v230() and later _v240() etc. AFAICS its 
only ever invoked via PMD_REGISTER_DRIVER() so the calling details can 
conveniently be hidden there.

	- Panu -
  

Patch

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 6c21fbd..3b12ee6 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -273,6 +273,10 @@  pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 	/* get subsystem_device id */
 	dev->id.subsystem_device_id = conf->pc_subdevice;
 
+	dev->id.class_id = (conf->pc_class << 16) |
+			   (conf->pc_subclass << 8) |
+			   (conf->pc_progif);
+
 	/* TODO: get max_vfs */
 	dev->max_vfs = 0;
 
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index dcfe947..6832821 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -162,6 +162,9 @@  rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d
 		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
 				id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
+		if (id_table->class_id != dev->id.class_id &&
+				id_table->class_id != CLASS_ANY_ID)
+			continue;
 
 		struct rte_pci_addr *loc = &dev->addr;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 334c12e..a538fbe 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -129,6 +129,7 @@  struct rte_pci_id {
 	uint16_t device_id;           /**< Device ID or PCI_ANY_ID. */
 	uint16_t subsystem_vendor_id; /**< Subsystem vendor ID or PCI_ANY_ID. */
 	uint16_t subsystem_device_id; /**< Subsystem device ID or PCI_ANY_ID. */
+	uint32_t class_id;           /**< Class ID (class, subclass, pi) or CLASS_ANY_ID. */
 };
 
 /**
@@ -170,6 +171,7 @@  struct rte_pci_device {
 
 /** Any PCI device identifier (vendor, device, ...) */
 #define PCI_ANY_ID (0xffff)
+#define CLASS_ANY_ID (0xffffff)
 
 #ifdef __cplusplus
 /** C++ macro used to help building up tables of device IDs */
@@ -177,14 +179,16 @@  struct rte_pci_device {
 	(vend),                   \
 	(dev),                    \
 	PCI_ANY_ID,               \
-	PCI_ANY_ID
+	PCI_ANY_ID,               \
+	CLASS_ANY_ID
 #else
 /** Macro used to help building up tables of device IDs */
 #define RTE_PCI_DEVICE(vend, dev)          \
 	.vendor_id = (vend),               \
 	.device_id = (dev),                \
 	.subsystem_vendor_id = PCI_ANY_ID, \
-	.subsystem_device_id = PCI_ANY_ID
+	.subsystem_device_id = PCI_ANY_ID, \
+	.class_id = CLASS_ANY_ID
 #endif
 
 struct rte_pci_driver;
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index bc5b5be..d9bfc0c 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -306,6 +306,15 @@  pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
 	}
 	dev->id.subsystem_device_id = (uint16_t)tmp;
 
+	/* get class_id */
+	snprintf(filename, sizeof(filename), "%s/class",
+		 dirname);
+	if (eal_parse_sysfs_value(filename, &tmp) < 0) {
+		free(dev);
+		return -1;
+	}
+	dev->id.class_id = (uint32_t)tmp && CLASS_ANY_ID;
+
 	/* get max_vfs */
 	dev->max_vfs = 0;
 	snprintf(filename, sizeof(filename), "%s/max_vfs", dirname);