PCI: Linux kernel SR-IOV support
Subsystems (4)
v4 cover PCI: Linux kernel SR-IOV support
Greetings,
Following patches are intended to support SR-IOV capability in the Linux kernel. With these patches, people can turn a PCI device with the capability into multiple ones from software perspective, which will benefit KVM and achieve other purposes such as QoS, security, and etc.
[PATCH 1/8 v4] PCI: define PCI resource names in a 'enum' [PATCH 2/8 v4] PCI: export __pci_read_base
[PATCH 3/8 v4] PCI: export pci_alloc_child_bus [PATCH 4/8 v4] PCI: add a wrapper for resource_alignment [PATCH 5/8 v4] PCI: add a new function to map BAR offset [PATCH 6/8 v4] PCI: support the SR-IOV capability [PATCH 7/8 v4] PCI: reserve bus range for the SR-IOV device [PATCH 8/8 v4] PCI: document the changes
---
b/Documentation/DocBook/kernel-api.tmpl | 1 b/Documentation/PCI/pci-iov-howto.txt | 223 ++++++++ b/drivers/pci/Kconfig | 12 b/drivers/pci/Makefile | 2 b/drivers/pci/iov.c | 853 ++++++++++++++++++++++++++++++++ b/drivers/pci/pci-sysfs.c | 4 b/drivers/pci/pci.c | 19 b/drivers/pci/pci.h | 9 b/drivers/pci/probe.c | 2 b/drivers/pci/proc.c | 7 b/drivers/pci/setup-bus.c | 4 b/drivers/pci/setup-res.c | 8 b/include/linux/pci.h | 38 - b/include/linux/pci_regs.h | 22 drivers/pci/iov.c | 24 drivers/pci/pci-sysfs.c | 4 drivers/pci/pci.c | 61 ++ drivers/pci/pci.h | 65 ++ drivers/pci/probe.c | 39 - drivers/pci/setup-res.c | 14 include/linux/pci.h | 57 ++ 21 files changed, 1397 insertions(+), 71 deletions(-)
---
Single Root I/O Virtualization (SR-IOV) capability defined by PCI-SIG is intended to enable multiple system software to share PCI hardware resources. PCI device that supports this capability can be extended to one Physical Functions plus multiple Virtual Functions. Physical Function, which could be considered as the "real" PCI device, reflects the hardware instance and manages all physical resources. Virtual Functions are associated with a Physical Function and shares physical resources with the Physical Function.Software can control allocation of Virtual Functions via registers encapsulated in the capability structure.
SR-IOV specification can be found at
http://www.pcisig.com/members/downloads/specifications/iov/sr-iov1.0_11Sep07.pdf
Devices that support SR-IOV are available from following vendors:
http://download.intel.com/design/network/ProdBrf/320025.pdf
http://www.netxen.com/products/chipsolutions/NX3031.html
http://www.neterion.com/products/x3100.html
PATCH v4 1/8 PCI: define PCI resource names in an 'enum'
This patch moves all definitions of PCI resource names to an 'enum', and also replaces some hard-coded resource variables with symbol names. This change eases the introduction of device specific resources.
--- drivers/pci/pci-sysfs.c | 4 +++- drivers/pci/pci.c | 19 ++----------------- drivers/pci/probe.c | 2 +- drivers/pci/proc.c | 7 ++++--- include/linux/pci.h | 37 ++++++++++++++++++++++++------------- 5 files changed, 34 insertions(+), 35 deletions(-)
drivers/pci/pci-sysfs.c +3 -1
@@ -101,11 +101,13 @@ resource_show(struct device * dev, struct device_attribute *attr, char * buf)struct pci_dev * pci_dev =to_pci_dev (dev);char * str = buf;int i; -int max =7 ; +int max;resource_size_t start, end;if (pci_dev->subordinate) max =DEVICE_COUNT_RESOURCE ; +else + max =PCI_BRIDGE_RESOURCES ;for (i =0 ; i < max; i++) {struct resource *res = &pci_dev->resource[i];
drivers/pci/pci.c +2 -17
@@ -359,24 +359,9 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)static void pci_restore_bars (struct pci_dev *dev) { -int i, numres; - -switch (dev->hdr_type) { -case PCI_HEADER_TYPE_NORMAL : - numres =6 ; -break ; -case PCI_HEADER_TYPE_BRIDGE : - numres =2 ; -break ; -case PCI_HEADER_TYPE_CARDBUS : - numres =1 ; -break ; -default : -/* Should never get here, but just in case... */ -return ; - } +int i; -for (i =0 ; i < numres; i++) +for (i =0 ; i <PCI_BRIDGE_RESOURCES ; i++)pci_update_resource (dev, i); }
drivers/pci/probe.c +1 -1
@@ -492,7 +492,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child->subordinate =0xff ;/* Set up default resource pointers and names.. */ -for (i =0 ; i <4 ; i++) { +for (i =0 ; i <PCI_BRIDGE_RES_NUM ; i++) { child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES +i]; child->resource[i]->name = child->name; }
drivers/pci/proc.c +4 -3
@@ -352,15 +352,16 @@ static int show_device(struct seq_file *m, void *v) dev->vendor, dev->device, dev->irq); -/* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */ -for (i=0 ; i<7 ; i++) { + +/* only print standard and ROM resources to preserve compatibility */ +for (i =0 ; i <=PCI_ROM_RESOURCE ; i++) {resource_size_t start, end;pci_resource_to_user (dev, i, &dev->resource[i], &start, &end);seq_printf (m,"\t%16llx" , (unsigned long long )(start | (dev->resource[i].flags &PCI_REGION_FLAG_MASK ))); } -for (i=0 ; i<7 ; i++) { +for (i =0 ; i <=PCI_ROM_RESOURCE ; i++) {resource_size_t start, end;pci_resource_to_user (dev, i, &dev->resource[i], &start, &end); seq_printf(m, "\t%16llx",
include/linux/pci.h +24 -13
@@ -76,7 +76,30 @@ enum pci_mmap_state {#define PCI_DMA_FROMDEVICE 2#define PCI_DMA_NONE 3 -#define DEVICE_COUNT_RESOURCE 12 +/* +* For PCI devices, the region numbers are assigned this way: +*/ +enum { +/* #0-5: standard PCI regions */ +PCI_STD_RESOURCES , +PCI_STD_RESOURCES_END =5 , + +/* #6: expansion ROM */ +PCI_ROM_RESOURCE , + +/* address space assigned to buses behind the bridge */ +#ifndef PCI_BRIDGE_RES_NUM +#define PCI_BRIDGE_RES_NUM 4 +#endif +PCI_BRIDGE_RESOURCES , +PCI_BRIDGE_RES_END =PCI_BRIDGE_RESOURCES +PCI_BRIDGE_RES_NUM -1 , + +/* total resources associated with a PCI device */ +PCI_NUM_RESOURCES , + +/* preserve this for compatibility */ +DEVICE_COUNT_RESOURCE +};typedef int __bitwise pci_power_t ;
@@ -262,18 +285,6 @@ static inline void pci_add_saved_cap(struct pci_dev *pci_dev,hlist_add_head (&new_cap->next, &pci_dev->saved_cap_space); } -/* -* For PCI devices, the region numbers are assigned this way: -* -* 0-5 standard PCI regions -* 6 expansion ROM -* 7-10 bridges: address space assigned to buses behind the bridge -*/ - -#define PCI_ROM_RESOURCE 6 -#define PCI_BRIDGE_RESOURCES 7 -#define PCI_NUM_RESOURCES 11 -#ifndef PCI_BUS_NUM_RESOURCES #define PCI_BUS_NUM_RESOURCES 16#endif
Signature · 1 line
1.5.6.4
PATCH v4 1/8 PCI: define PCI resource names in an 'enum'
In reply to Yu ZhaoThis patch moves all definitions of PCI resource names to an 'enum', and also replaces some hard-coded resource variables with symbol names. This change eases the introduction of device specific resources.
--- drivers/pci/pci-sysfs.c | 4 +++- drivers/pci/pci.c | 19 ++----------------- drivers/pci/probe.c | 2 +- drivers/pci/proc.c | 7 ++++--- include/linux/pci.h | 37 ++++++++++++++++++++++++------------- 5 files changed, 34 insertions(+), 35 deletions(-)
drivers/pci/pci-sysfs.c +3 -1
@@ -101,11 +101,13 @@ resource_show(struct device * dev, struct device_attribute *attr, char * buf)struct pci_dev * pci_dev =to_pci_dev (dev);char * str = buf;int i; -int max =7 ; +int max;resource_size_t start, end;if (pci_dev->subordinate) max =DEVICE_COUNT_RESOURCE ; +else + max =PCI_BRIDGE_RESOURCES ;for (i =0 ; i < max; i++) {struct resource *res = &pci_dev->resource[i];
drivers/pci/pci.c +2 -17
@@ -359,24 +359,9 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)static void pci_restore_bars (struct pci_dev *dev) { -int i, numres; - -switch (dev->hdr_type) { -case PCI_HEADER_TYPE_NORMAL : - numres =6 ; -break ; -case PCI_HEADER_TYPE_BRIDGE : - numres =2 ; -break ; -case PCI_HEADER_TYPE_CARDBUS : - numres =1 ; -break ; -default : -/* Should never get here, but just in case... */ -return ; - } +int i; -for (i =0 ; i < numres; i++) +for (i =0 ; i <PCI_BRIDGE_RESOURCES ; i++)pci_update_resource (dev, i); }
drivers/pci/probe.c +1 -1
@@ -492,7 +492,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child->subordinate =0xff ;/* Set up default resource pointers and names.. */ -for (i =0 ; i <4 ; i++) { +for (i =0 ; i <PCI_BRIDGE_RES_NUM ; i++) { child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES +i]; child->resource[i]->name = child->name; }
drivers/pci/proc.c +4 -3
@@ -352,15 +352,16 @@ static int show_device(struct seq_file *m, void *v) dev->vendor, dev->device, dev->irq); -/* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */ -for (i=0 ; i<7 ; i++) { + +/* only print standard and ROM resources to preserve compatibility */ +for (i =0 ; i <=PCI_ROM_RESOURCE ; i++) {resource_size_t start, end;pci_resource_to_user (dev, i, &dev->resource[i], &start, &end);seq_printf (m,"\t%16llx" , (unsigned long long )(start | (dev->resource[i].flags &PCI_REGION_FLAG_MASK ))); } -for (i=0 ; i<7 ; i++) { +for (i =0 ; i <=PCI_ROM_RESOURCE ; i++) {resource_size_t start, end;pci_resource_to_user (dev, i, &dev->resource[i], &start, &end); seq_printf(m, "\t%16llx",
include/linux/pci.h +24 -13
@@ -76,7 +76,30 @@ enum pci_mmap_state {#define PCI_DMA_FROMDEVICE 2#define PCI_DMA_NONE 3 -#define DEVICE_COUNT_RESOURCE 12 +/* +* For PCI devices, the region numbers are assigned this way: +*/ +enum { +/* #0-5: standard PCI regions */ +PCI_STD_RESOURCES , +PCI_STD_RESOURCES_END =5 , + +/* #6: expansion ROM */ +PCI_ROM_RESOURCE , + +/* address space assigned to buses behind the bridge */ +#ifndef PCI_BRIDGE_RES_NUM +#define PCI_BRIDGE_RES_NUM 4 +#endif +PCI_BRIDGE_RESOURCES , +PCI_BRIDGE_RES_END =PCI_BRIDGE_RESOURCES +PCI_BRIDGE_RES_NUM -1 , + +/* total resources associated with a PCI device */ +PCI_NUM_RESOURCES , + +/* preserve this for compatibility */ +DEVICE_COUNT_RESOURCE +};typedef int __bitwise pci_power_t ;
@@ -262,18 +285,6 @@ static inline void pci_add_saved_cap(struct pci_dev *pci_dev,hlist_add_head (&new_cap->next, &pci_dev->saved_cap_space); } -/* -* For PCI devices, the region numbers are assigned this way: -* -* 0-5 standard PCI regions -* 6 expansion ROM -* 7-10 bridges: address space assigned to buses behind the bridge -*/ - -#define PCI_ROM_RESOURCE 6 -#define PCI_BRIDGE_RESOURCES 7 -#define PCI_NUM_RESOURCES 11 -#ifndef PCI_BUS_NUM_RESOURCES #define PCI_BUS_NUM_RESOURCES 16#endif
Signature · 1 line
1.5.6.4
PATCH v4 2/8 PCI: export __pci_read_base
In reply to Yu ZhaoExport __pci_read_base() so it can be used by whole PCI subsystem.
--- drivers/pci/pci.h | 9 +++++++++ drivers/pci/probe.c | 20 +++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-)
drivers/pci/pci.h +9 -0
@@ -150,6 +150,15 @@ struct pci_slot_attribute { };#define to_pci_slot_attr (s) container_of(s, struct pci_slot_attribute, attr) +enum pci_bar_type { + pci_bar_unknown,/* Standard PCI BAR probe */ + pci_bar_io,/* An io port BAR */ + pci_bar_mem32,/* A 32-bit memory BAR */ + pci_bar_mem64,/* A 64-bit memory BAR */ +}; + +extern int __pci_read_base (struct pci_dev *dev,enum pci_bar_type type, +struct resource *res,unsigned int reg);extern void pci_enable_ari (struct pci_dev *dev);/** * pci_ari_enabled - query ARI forwarding status
drivers/pci/probe.c +9 -11
@@ -201,13 +201,6 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask)return size; } -enum pci_bar_type { - pci_bar_unknown,/* Standard PCI BAR probe */ - pci_bar_io,/* An io port BAR */ - pci_bar_mem32,/* A 32-bit memory BAR */ - pci_bar_mem64,/* A 64-bit memory BAR */ -}; -static inline enum pci_bar_type decode_bar (struct resource *res,u32 bar) {if ((bar &PCI_BASE_ADDRESS_SPACE ) ==PCI_BASE_ADDRESS_SPACE_IO ) {
@@ -222,11 +215,16 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)return pci_bar_mem32; } -/* -* If the type is not unknown, we assume that the lowest bit is 'enable'. -* Returns 1 if the BAR was 64-bit and 0 if it was 32-bit. +/** +* pci_read_base - read a PCI BAR +* @dev: the PCI device +* @type: type of the BAR +* @res: resource buffer to be filled in +* @pos: BAR position in the config space +* +* Returns 1 if the BAR is 64-bit, or 0 if 32-bit. */ -static int __pci_read_base (struct pci_dev *dev,enum pci_bar_type type, +int __pci_read_base (struct pci_dev *dev,enum pci_bar_type type,struct resource *res,unsigned int pos) {u32 l, sz, mask;
Signature · 1 line
1.5.6.4
PATCH v4 2/8 PCI: export __pci_read_base
In reply to Yu ZhaoExport __pci_read_base() so it can be used by whole PCI subsystem.
--- drivers/pci/pci.h | 9 +++++++++ drivers/pci/probe.c | 20 +++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-)
drivers/pci/pci.h +9 -0
@@ -150,6 +150,15 @@ struct pci_slot_attribute { };#define to_pci_slot_attr (s) container_of(s, struct pci_slot_attribute, attr) +enum pci_bar_type { + pci_bar_unknown,/* Standard PCI BAR probe */ + pci_bar_io,/* An io port BAR */ + pci_bar_mem32,/* A 32-bit memory BAR */ + pci_bar_mem64,/* A 64-bit memory BAR */ +}; + +extern int __pci_read_base (struct pci_dev *dev,enum pci_bar_type type, +struct resource *res,unsigned int reg);extern void pci_enable_ari (struct pci_dev *dev);/** * pci_ari_enabled - query ARI forwarding status
drivers/pci/probe.c +9 -11
@@ -201,13 +201,6 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask)return size; } -enum pci_bar_type { - pci_bar_unknown,/* Standard PCI BAR probe */ - pci_bar_io,/* An io port BAR */ - pci_bar_mem32,/* A 32-bit memory BAR */ - pci_bar_mem64,/* A 64-bit memory BAR */ -}; -static inline enum pci_bar_type decode_bar (struct resource *res,u32 bar) {if ((bar &PCI_BASE_ADDRESS_SPACE ) ==PCI_BASE_ADDRESS_SPACE_IO ) {
@@ -222,11 +215,16 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)return pci_bar_mem32; } -/* -* If the type is not unknown, we assume that the lowest bit is 'enable'. -* Returns 1 if the BAR was 64-bit and 0 if it was 32-bit. +/** +* pci_read_base - read a PCI BAR +* @dev: the PCI device +* @type: type of the BAR +* @res: resource buffer to be filled in +* @pos: BAR position in the config space +* +* Returns 1 if the BAR is 64-bit, or 0 if 32-bit. */ -static int __pci_read_base (struct pci_dev *dev,enum pci_bar_type type, +int __pci_read_base (struct pci_dev *dev,enum pci_bar_type type,struct resource *res,unsigned int pos) {u32 l, sz, mask;
Signature · 1 line
1.5.6.4
PATCH v4 3/8 PCI: export pci_alloc_child_bus
In reply to Yu ZhaoExport pci_alloc_child_bus(), and make it be able to handle buses without bridge devices. Some devices such as SR-IOV devices use more than one bus number while there is no explicit bridge devices since they have internal routing mechanism.
--- drivers/pci/pci.h | 2 ++ drivers/pci/probe.c | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-)
drivers/pci/pci.h +2 -0
@@ -159,6 +159,8 @@ enum pci_bar_type {extern int __pci_read_base (struct pci_dev *dev,enum pci_bar_type type,struct resource *res,unsigned int reg); +extern struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent, +struct pci_dev *bridge,int busnr);extern void pci_enable_ari (struct pci_dev *dev);/** * pci_ari_enabled - query ARI forwarding status
drivers/pci/probe.c +6 -3
@@ -454,7 +454,7 @@ static struct pci_bus * pci_alloc_bus(void)return b; } -static struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent, +struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent,struct pci_dev *bridge,int busnr) {struct pci_bus *child;
@@ -467,12 +467,10 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,if (!child)return NULL ; - child->self = bridge; child->parent = parent; child->ops = parent->ops; child->sysdata = parent->sysdata; child->bus_flags = parent->bus_flags; - child->bridge =get_device (&bridge->dev);/* initialize some portions of the bus device, but don't register it * now as the parent is not properly set up yet. This device will get
@@ -489,6 +487,11 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child->primary = parent->secondary; child->subordinate =0xff ; +if (!bridge) +return child; + + child->self = bridge; + child->bridge =get_device (&bridge->dev);/* Set up default resource pointers and names.. */ for (i =0 ; i <PCI_BRIDGE_RES_NUM ; i++) { child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES +i];
Signature · 1 line
1.5.6.4
PATCH v4 3/8 PCI: export pci_alloc_child_bus
In reply to Yu ZhaoExport pci_alloc_child_bus(), and make it be able to handle buses without bridge devices. Some devices such as SR-IOV devices use more than one bus number while there is no explicit bridge devices since they have internal routing mechanism.
--- drivers/pci/pci.h | 2 ++ drivers/pci/probe.c | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-)
drivers/pci/pci.h +2 -0
@@ -159,6 +159,8 @@ enum pci_bar_type {extern int __pci_read_base (struct pci_dev *dev,enum pci_bar_type type,struct resource *res,unsigned int reg); +extern struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent, +struct pci_dev *bridge,int busnr);extern void pci_enable_ari (struct pci_dev *dev);/** * pci_ari_enabled - query ARI forwarding status
drivers/pci/probe.c +6 -3
@@ -454,7 +454,7 @@ static struct pci_bus * pci_alloc_bus(void)return b; } -static struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent, +struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent,struct pci_dev *bridge,int busnr) {struct pci_bus *child;
@@ -467,12 +467,10 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,if (!child)return NULL ; - child->self = bridge; child->parent = parent; child->ops = parent->ops; child->sysdata = parent->sysdata; child->bus_flags = parent->bus_flags; - child->bridge =get_device (&bridge->dev);/* initialize some portions of the bus device, but don't register it * now as the parent is not properly set up yet. This device will get
@@ -489,6 +487,11 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, child->primary = parent->secondary; child->subordinate =0xff ; +if (!bridge) +return child; + + child->self = bridge; + child->bridge =get_device (&bridge->dev);/* Set up default resource pointers and names.. */ for (i =0 ; i <PCI_BRIDGE_RES_NUM ; i++) { child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES +i];
Signature · 1 line
1.5.6.4
PATCH v4 4/8 PCI: add a wrapper for resource_alignment
In reply to Yu ZhaoAdd a wrap of resource_alignment so it can handle device specific resource alignment.
--- drivers/pci/pci.c | 25 +++++++++++++++++++++++++ drivers/pci/pci.h | 1 + drivers/pci/setup-bus.c | 4 ++-- drivers/pci/setup-res.c | 7 ++++--- 4 files changed, 32 insertions(+), 5 deletions(-)
drivers/pci/pci.c +25 -0
@@ -1884,6 +1884,31 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags)return bars; } +/** +* pci_resource_alignment - get a PCI BAR resource alignment +* @dev: the PCI device +* @resno: the resource number +* +* Returns alignment size on success, or 0 on error. +*/ +int pci_resource_alignment (struct pci_dev *dev,int resno) +{ +resource_size_t align; +struct resource *res = dev->resource + resno; + + align =resource_alignment (res); +if (align) +return align; + +if (resno <=PCI_ROM_RESOURCE ) +return resource_size (res); +else if (resno <=PCI_BRIDGE_RES_END ) +return res->start; + +dev_err (&dev->dev,"alignment: invalid resource #%d\n" , resno); +return 0 ; +} +static void __devinit pci_no_domains (void ) {#ifdef CONFIG_PCI_DOMAINS
drivers/pci/pci.h +1 -0
@@ -161,6 +161,7 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, struct resource *res, unsigned int reg);extern struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent,struct pci_dev *bridge,int busnr); +extern int pci_resource_alignment (struct pci_dev *dev,int resno);extern void pci_enable_ari (struct pci_dev *dev);/** * pci_ari_enabled - query ARI forwarding status
drivers/pci/setup-bus.c +2 -2
@@ -25,6 +25,7 @@#include <linux/ioport.h> #include <linux/cache.h> #include <linux/slab.h> +#include "pci.h" static void pbus_assign_resources_sorted (struct pci_bus *bus)
@@ -351,8 +352,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned longif (r->parent || (r->flags & mask) != type)continue ; r_size =resource_size (r); -/* For bridges size != alignment */ - align =resource_alignment (r); + align =pci_resource_alignment (dev, i); order =__ffs (align) -20 ;if (order >11 ) { dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
drivers/pci/setup-res.c +4 -3
@@ -137,7 +137,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno) size =resource_size (res); min = (res->flags &IORESOURCE_IO ) ?PCIBIOS_MIN_IO :PCIBIOS_MIN_MEM ; - align =resource_alignment (res); + align =pci_resource_alignment (dev, resno);if (!align) { dev_err(&dev->dev, "BAR %d: can't allocate resource (bogus " "alignment) [%#llx-%#llx] flags %#lx\n",
@@ -235,7 +235,7 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)if (!(r->flags) || r->parent)continue ; - r_align =resource_alignment (r); + r_align =pci_resource_alignment (dev, i);if (!r_align) { dev_warn(&dev->dev, "BAR %d: bogus alignment " "[%#llx-%#llx] flags %#lx\n",
@@ -248,7 +248,8 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)struct resource_list *ln = list->next;if (ln) - align =resource_alignment (ln->res); + align =pci_resource_alignment (ln->dev, + ln->res - ln->dev->resource);if (r_align > align) { tmp =kmalloc (sizeof (*tmp),GFP_KERNEL );
Signature · 1 line
1.5.6.4
PATCH v4 4/8 PCI: add a wrapper for resource_alignment
In reply to Yu ZhaoAdd a wrap of resource_alignment so it can handle device specific resource alignment.
--- drivers/pci/pci.c | 25 +++++++++++++++++++++++++ drivers/pci/pci.h | 1 + drivers/pci/setup-bus.c | 4 ++-- drivers/pci/setup-res.c | 7 ++++--- 4 files changed, 32 insertions(+), 5 deletions(-)
drivers/pci/pci.c +25 -0
@@ -1884,6 +1884,31 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags)return bars; } +/** +* pci_resource_alignment - get a PCI BAR resource alignment +* @dev: the PCI device +* @resno: the resource number +* +* Returns alignment size on success, or 0 on error. +*/ +int pci_resource_alignment (struct pci_dev *dev,int resno) +{ +resource_size_t align; +struct resource *res = dev->resource + resno; + + align =resource_alignment (res); +if (align) +return align; + +if (resno <=PCI_ROM_RESOURCE ) +return resource_size (res); +else if (resno <=PCI_BRIDGE_RES_END ) +return res->start; + +dev_err (&dev->dev,"alignment: invalid resource #%d\n" , resno); +return 0 ; +} +static void __devinit pci_no_domains (void ) {#ifdef CONFIG_PCI_DOMAINS
drivers/pci/pci.h +1 -0
@@ -161,6 +161,7 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, struct resource *res, unsigned int reg);extern struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent,struct pci_dev *bridge,int busnr); +extern int pci_resource_alignment (struct pci_dev *dev,int resno);extern void pci_enable_ari (struct pci_dev *dev);/** * pci_ari_enabled - query ARI forwarding status
drivers/pci/setup-bus.c +2 -2
@@ -25,6 +25,7 @@#include <linux/ioport.h> #include <linux/cache.h> #include <linux/slab.h> +#include "pci.h" static void pbus_assign_resources_sorted (struct pci_bus *bus)
@@ -351,8 +352,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned longif (r->parent || (r->flags & mask) != type)continue ; r_size =resource_size (r); -/* For bridges size != alignment */ - align =resource_alignment (r); + align =pci_resource_alignment (dev, i); order =__ffs (align) -20 ;if (order >11 ) { dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
drivers/pci/setup-res.c +4 -3
@@ -137,7 +137,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno) size =resource_size (res); min = (res->flags &IORESOURCE_IO ) ?PCIBIOS_MIN_IO :PCIBIOS_MIN_MEM ; - align =resource_alignment (res); + align =pci_resource_alignment (dev, resno);if (!align) { dev_err(&dev->dev, "BAR %d: can't allocate resource (bogus " "alignment) [%#llx-%#llx] flags %#lx\n",
@@ -235,7 +235,7 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)if (!(r->flags) || r->parent)continue ; - r_align =resource_alignment (r); + r_align =pci_resource_alignment (dev, i);if (!r_align) { dev_warn(&dev->dev, "BAR %d: bogus alignment " "[%#llx-%#llx] flags %#lx\n",
@@ -248,7 +248,8 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)struct resource_list *ln = list->next;if (ln) - align =resource_alignment (ln->res); + align =pci_resource_alignment (ln->dev, + ln->res - ln->dev->resource);if (r_align > align) { tmp =kmalloc (sizeof (*tmp),GFP_KERNEL );
Signature · 1 line
1.5.6.4
PATCH v4 5/8 PCI: add a new function to map BAR offset
In reply to Yu ZhaoAdd a new function to map resource number to base register (offset and type).
--- drivers/pci/pci.c | 22 ++++++++++++++++++++++ drivers/pci/pci.h | 2 ++ drivers/pci/setup-res.c | 13 +++++-------- 3 files changed, 29 insertions(+), 8 deletions(-)
drivers/pci/pci.c +22 -0
@@ -1909,6 +1909,28 @@ int pci_resource_alignment(struct pci_dev *dev, int resno)return 0 ; } +/** +* pci_resource_bar - get position of the BAR associated with a resource +* @dev: the PCI device +* @resno: the resource number +* @type: the BAR type to be filled in +* +* Returns BAR position in config space, or 0 if the BAR is invalid. +*/ +int pci_resource_bar (struct pci_dev *dev,int resno,enum pci_bar_type *type) +{ +if (resno <PCI_ROM_RESOURCE ) { + *type = pci_bar_unknown; +return PCI_BASE_ADDRESS_0 +4 * resno; + }else if (resno ==PCI_ROM_RESOURCE ) { + *type = pci_bar_mem32; +return dev->rom_base_reg; + } + +dev_err (&dev->dev,"BAR: invalid resource #%d\n" , resno); +return 0 ; +} +static void __devinit pci_no_domains (void ) {#ifdef CONFIG_PCI_DOMAINS
drivers/pci/pci.h +2 -0
@@ -162,6 +162,8 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,extern struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent,struct pci_dev *bridge,int busnr);extern int pci_resource_alignment (struct pci_dev *dev,int resno); +extern int pci_resource_bar (struct pci_dev *dev,int resno, +enum pci_bar_type *type);extern void pci_enable_ari (struct pci_dev *dev);/** * pci_ari_enabled - query ARI forwarding status
drivers/pci/setup-res.c +5 -8
@@ -31,6 +31,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)struct pci_bus_region region;u32 new, check, mask;int reg; +enum pci_bar_type type;struct resource *res = dev->resource + resno;/*
@@ -64,17 +65,13 @@ void pci_update_resource(struct pci_dev *dev, int resno)else mask = (u32 )PCI_BASE_ADDRESS_MEM_MASK ; -if (resno <6 ) { - reg =PCI_BASE_ADDRESS_0 +4 * resno; - }else if (resno ==PCI_ROM_RESOURCE ) { + reg =pci_resource_bar (dev, resno, &type); +if (!reg) +return ; +if (type != pci_bar_unknown) {if (!(res->flags &IORESOURCE_ROM_ENABLE ))return ; new |=PCI_ROM_ADDRESS_ENABLE ; - reg = dev->rom_base_reg; - }else { -/* Hmm, non-standard resource. */ - -return ;/* kill uninitialised var warning */ }pci_write_config_dword (dev, reg, new);
Signature · 1 line
1.5.6.4
PATCH v4 5/8 PCI: add a new function to map BAR offset
In reply to Yu ZhaoAdd a new function to map resource number to base register (offset and type).
--- drivers/pci/pci.c | 22 ++++++++++++++++++++++ drivers/pci/pci.h | 2 ++ drivers/pci/setup-res.c | 13 +++++-------- 3 files changed, 29 insertions(+), 8 deletions(-)
drivers/pci/pci.c +22 -0
@@ -1909,6 +1909,28 @@ int pci_resource_alignment(struct pci_dev *dev, int resno)return 0 ; } +/** +* pci_resource_bar - get position of the BAR associated with a resource +* @dev: the PCI device +* @resno: the resource number +* @type: the BAR type to be filled in +* +* Returns BAR position in config space, or 0 if the BAR is invalid. +*/ +int pci_resource_bar (struct pci_dev *dev,int resno,enum pci_bar_type *type) +{ +if (resno <PCI_ROM_RESOURCE ) { + *type = pci_bar_unknown; +return PCI_BASE_ADDRESS_0 +4 * resno; + }else if (resno ==PCI_ROM_RESOURCE ) { + *type = pci_bar_mem32; +return dev->rom_base_reg; + } + +dev_err (&dev->dev,"BAR: invalid resource #%d\n" , resno); +return 0 ; +} +static void __devinit pci_no_domains (void ) {#ifdef CONFIG_PCI_DOMAINS
drivers/pci/pci.h +2 -0
@@ -162,6 +162,8 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,extern struct pci_bus *pci_alloc_child_bus (struct pci_bus *parent,struct pci_dev *bridge,int busnr);extern int pci_resource_alignment (struct pci_dev *dev,int resno); +extern int pci_resource_bar (struct pci_dev *dev,int resno, +enum pci_bar_type *type);extern void pci_enable_ari (struct pci_dev *dev);/** * pci_ari_enabled - query ARI forwarding status
drivers/pci/setup-res.c +5 -8
@@ -31,6 +31,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)struct pci_bus_region region;u32 new, check, mask;int reg; +enum pci_bar_type type;struct resource *res = dev->resource + resno;/*
@@ -64,17 +65,13 @@ void pci_update_resource(struct pci_dev *dev, int resno)else mask = (u32 )PCI_BASE_ADDRESS_MEM_MASK ; -if (resno <6 ) { - reg =PCI_BASE_ADDRESS_0 +4 * resno; - }else if (resno ==PCI_ROM_RESOURCE ) { + reg =pci_resource_bar (dev, resno, &type); +if (!reg) +return ; +if (type != pci_bar_unknown) {if (!(res->flags &IORESOURCE_ROM_ENABLE ))return ; new |=PCI_ROM_ADDRESS_ENABLE ; - reg = dev->rom_base_reg; - }else { -/* Hmm, non-standard resource. */ - -return ;/* kill uninitialised var warning */ }pci_write_config_dword (dev, reg, new);
Signature · 1 line
1.5.6.4
PATCH v4 6/8 PCI: support the SR-IOV capability
In reply to Yu ZhaoSupport Single Root I/O Virtualization (SR-IOV) capability.
--- drivers/pci/Kconfig | 12 + drivers/pci/Makefile | 2 + drivers/pci/iov.c | 853 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/pci-sysfs.c | 4 + drivers/pci/pci.c | 14 +- drivers/pci/pci.h | 55 +++ drivers/pci/probe.c | 4 + include/linux/pci.h | 57 +++ include/linux/pci_regs.h | 21 ++ 9 files changed, 1021 insertions(+), 1 deletions(-) create mode 100644 drivers/pci/iov.c
drivers/pci/Kconfig +12 -0
@@ -50,3 +50,15 @@ config HT_IRQ This allows native hypertransport devices to use interrupts. If unsure say Y. + +config PCI_IOV + bool "PCI SR-IOV support" + depends on PCI + select PCI_MSI + default n + help + This option allows device drivers to enable Single Root I/O + Virtualization. Each Virtual Function's PCI configuration + space can be accessed using its own Bus, Device and Function + Number (Routing ID). Each Virtual Function also has PCI Memory + Space, which is used to map its own register set.
drivers/pci/Makefile +2 -0
@@ -53,3 +53,5 @@ obj-$(CONFIG_PCI_SYSCALL) += syscall.o ifeq ($(CONFIG_PCI_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif + +obj-$(CONFIG_PCI_IOV) += iov.o
drivers/pci/iov.c new file +853 -0
853 lines not on this page · raw message
drivers/pci/pci-sysfs.c +4 -0
@@ -764,6 +764,9 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)/* Active State Power Management */ pcie_aspm_create_sysfs_dev_files (dev); +/* Single Root I/O Virtualization */ +pci_iov_create_sysfs (dev); +return 0 ; }
@@ -849,6 +852,7 @@ static void pci_remove_capabilities_sysfs(struct pci_dev *dev) }pcie_aspm_remove_sysfs_dev_files (dev); +pci_iov_remove_sysfs (dev); }/**
drivers/pci/pci.c +13 -1
@@ -1902,7 +1902,12 @@ int pci_resource_alignment(struct pci_dev *dev, int resno)if (resno <=PCI_ROM_RESOURCE )return resource_size (res); -else if (resno <=PCI_BRIDGE_RES_END ) +else if (resno <PCI_BRIDGE_RESOURCES ) { +/* may be device specific resource */ + align =pci_iov_resource_align (dev, resno); +if (align) +return align; + }else if (resno <=PCI_BRIDGE_RES_END )return res->start;dev_err (&dev->dev,"alignment: invalid resource #%d\n" , resno);
@@ -1919,12 +1924,19 @@ int pci_resource_alignment(struct pci_dev *dev, int resno)*/ int pci_resource_bar (struct pci_dev *dev,int resno,enum pci_bar_type *type) { +int reg; +if (resno <PCI_ROM_RESOURCE ) { *type = pci_bar_unknown;return PCI_BASE_ADDRESS_0 +4 * resno; }else if (resno ==PCI_ROM_RESOURCE ) { *type = pci_bar_mem32;return dev->rom_base_reg; + }else if (resno <PCI_BRIDGE_RESOURCES ) { +/* may be device specific resource */ + reg =pci_iov_resource_bar (dev, resno, type); +if (reg) +return reg; }dev_err (&dev->dev,"BAR: invalid resource #%d\n" , resno);
drivers/pci/pci.h +55 -0
59 lines not on this page · raw message
drivers/pci/probe.c +4 -0
@@ -845,6 +845,7 @@ static int pci_setup_device(struct pci_dev * dev)static void pci_release_capabilities (struct pci_dev *dev) {pci_vpd_release (dev); +pci_iov_release (dev); }/**
@@ -1023,6 +1024,9 @@ static void pci_init_capabilities(struct pci_dev *dev)/* Alternative Routing-ID Forwarding */ pci_enable_ari (dev); + +/* Single Root I/O Virtualization */ +pci_iov_init (dev); }void pci_device_add (struct pci_dev *dev,struct pci_bus *bus)
include/linux/pci.h +57 -0
80 lines not on this page · raw message
include/linux/pci_regs.h +21 -0
@@ -363,6 +363,7 @@#define PCI_EXP_TYPE_UPSTREAM 0x5/* Upstream Port */ #define PCI_EXP_TYPE_DOWNSTREAM 0x6/* Downstream Port */ #define PCI_EXP_TYPE_PCI_BRIDGE 0x7/* PCI/PCI-X Bridge */ +#define PCI_EXP_TYPE_RC_END 0x9/* Root Complex Integrated Endpoint */ #define PCI_EXP_FLAGS_SLOT 0x0100/* Slot implemented */ #define PCI_EXP_FLAGS_IRQ 0x3e00/* Interrupt message number */ #define PCI_EXP_DEVCAP 4/* Device capabilities */
@@ -434,6 +435,7 @@#define PCI_EXT_CAP_ID_DSN 3#define PCI_EXT_CAP_ID_PWR 4#define PCI_EXT_CAP_ID_ARI 14 +#define PCI_EXT_CAP_ID_IOV 16/* Advanced Error Reporting */ #define PCI_ERR_UNCOR_STATUS 4/* Uncorrectable Error Status */
@@ -551,4 +553,23 @@#define PCI_ARI_CTRL_ACS 0x0002/* ACS Function Groups Enable */ #define PCI_ARI_CTRL_FG (x) (((x) >> 4) & 7)/* Function Group */ +/* Single Root I/O Virtualization */ +#define PCI_IOV_CAP 0x04/* SR-IOV Capabilities */ +#define PCI_IOV_CTRL 0x08/* SR-IOV Control */ +#define PCI_IOV_CTRL_VFE 0x01/* VF Enable */ +#define PCI_IOV_CTRL_MSE 0x08/* VF Memory Space Enable */ +#define PCI_IOV_CTRL_ARI 0x10/* ARI Capable Hierarchy */ +#define PCI_IOV_STATUS 0x0a/* SR-IOV Status */ +#define PCI_IOV_INITIAL_VF 0x0c/* Initial VFs */ +#define PCI_IOV_TOTAL_VF 0x0e/* Total VFs */ +#define PCI_IOV_NUM_VF 0x10/* Number of VFs */ +#define PCI_IOV_FUNC_LINK 0x12/* Function Dependency Link */ +#define PCI_IOV_VF_OFFSET 0x14/* First VF Offset */ +#define PCI_IOV_VF_STRIDE 0x16/* Following VF Stride */ +#define PCI_IOV_VF_DID 0x1a/* VF Device ID */ +#define PCI_IOV_SUP_PGSIZE 0x1c/* Supported Page Sizes */ +#define PCI_IOV_SYS_PGSIZE 0x20/* System Page Size */ +#define PCI_IOV_BAR_0 0x24/* VF BAR0 */ +#define PCI_IOV_NUM_BAR 6/* Number of VF BARs */ +#endif /* LINUX_PCI_REGS_H */
Signature · 1 line
1.5.6.4
PATCH v4 6/8 PCI: support the SR-IOV capability
In reply to Yu ZhaoSupport Single Root I/O Virtualization (SR-IOV) capability.
--- drivers/pci/Kconfig | 12 + drivers/pci/Makefile | 2 + drivers/pci/iov.c | 853 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/pci-sysfs.c | 4 + drivers/pci/pci.c | 14 +- drivers/pci/pci.h | 55 +++ drivers/pci/probe.c | 4 + include/linux/pci.h | 57 +++ include/linux/pci_regs.h | 21 ++ 9 files changed, 1021 insertions(+), 1 deletions(-) create mode 100644 drivers/pci/iov.c
drivers/pci/Kconfig +12 -0
@@ -50,3 +50,15 @@ config HT_IRQ This allows native hypertransport devices to use interrupts. If unsure say Y. + +config PCI_IOV + bool "PCI SR-IOV support" + depends on PCI + select PCI_MSI + default n + help + This option allows device drivers to enable Single Root I/O + Virtualization. Each Virtual Function's PCI configuration + space can be accessed using its own Bus, Device and Function + Number (Routing ID). Each Virtual Function also has PCI Memory + Space, which is used to map its own register set.
drivers/pci/Makefile +2 -0
@@ -53,3 +53,5 @@ obj-$(CONFIG_PCI_SYSCALL) += syscall.o ifeq ($(CONFIG_PCI_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif + +obj-$(CONFIG_PCI_IOV) += iov.o
drivers/pci/iov.c new file +853 -0
853 lines not on this page · raw message
drivers/pci/pci-sysfs.c +4 -0
@@ -764,6 +764,9 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)/* Active State Power Management */ pcie_aspm_create_sysfs_dev_files (dev); +/* Single Root I/O Virtualization */ +pci_iov_create_sysfs (dev); +return 0 ; }
@@ -849,6 +852,7 @@ static void pci_remove_capabilities_sysfs(struct pci_dev *dev) }pcie_aspm_remove_sysfs_dev_files (dev); +pci_iov_remove_sysfs (dev); }/**
drivers/pci/pci.c +13 -1
@@ -1902,7 +1902,12 @@ int pci_resource_alignment(struct pci_dev *dev, int resno)if (resno <=PCI_ROM_RESOURCE )return resource_size (res); -else if (resno <=PCI_BRIDGE_RES_END ) +else if (resno <PCI_BRIDGE_RESOURCES ) { +/* may be device specific resource */ + align =pci_iov_resource_align (dev, resno); +if (align) +return align; + }else if (resno <=PCI_BRIDGE_RES_END )return res->start;dev_err (&dev->dev,"alignment: invalid resource #%d\n" , resno);
@@ -1919,12 +1924,19 @@ int pci_resource_alignment(struct pci_dev *dev, int resno)*/ int pci_resource_bar (struct pci_dev *dev,int resno,enum pci_bar_type *type) { +int reg; +if (resno <PCI_ROM_RESOURCE ) { *type = pci_bar_unknown;return PCI_BASE_ADDRESS_0 +4 * resno; }else if (resno ==PCI_ROM_RESOURCE ) { *type = pci_bar_mem32;return dev->rom_base_reg; + }else if (resno <PCI_BRIDGE_RESOURCES ) { +/* may be device specific resource */ + reg =pci_iov_resource_bar (dev, resno, type); +if (reg) +return reg; }dev_err (&dev->dev,"BAR: invalid resource #%d\n" , resno);
drivers/pci/pci.h +55 -0
59 lines not on this page · raw message
drivers/pci/probe.c +4 -0
@@ -845,6 +845,7 @@ static int pci_setup_device(struct pci_dev * dev)static void pci_release_capabilities (struct pci_dev *dev) {pci_vpd_release (dev); +pci_iov_release (dev); }/**
@@ -1023,6 +1024,9 @@ static void pci_init_capabilities(struct pci_dev *dev)/* Alternative Routing-ID Forwarding */ pci_enable_ari (dev); + +/* Single Root I/O Virtualization */ +pci_iov_init (dev); }void pci_device_add (struct pci_dev *dev,struct pci_bus *bus)
include/linux/pci.h +57 -0
80 lines not on this page · raw message
include/linux/pci_regs.h +21 -0
@@ -363,6 +363,7 @@#define PCI_EXP_TYPE_UPSTREAM 0x5/* Upstream Port */ #define PCI_EXP_TYPE_DOWNSTREAM 0x6/* Downstream Port */ #define PCI_EXP_TYPE_PCI_BRIDGE 0x7/* PCI/PCI-X Bridge */ +#define PCI_EXP_TYPE_RC_END 0x9/* Root Complex Integrated Endpoint */ #define PCI_EXP_FLAGS_SLOT 0x0100/* Slot implemented */ #define PCI_EXP_FLAGS_IRQ 0x3e00/* Interrupt message number */ #define PCI_EXP_DEVCAP 4/* Device capabilities */
@@ -434,6 +435,7 @@#define PCI_EXT_CAP_ID_DSN 3#define PCI_EXT_CAP_ID_PWR 4#define PCI_EXT_CAP_ID_ARI 14 +#define PCI_EXT_CAP_ID_IOV 16/* Advanced Error Reporting */ #define PCI_ERR_UNCOR_STATUS 4/* Uncorrectable Error Status */
@@ -551,4 +553,23 @@#define PCI_ARI_CTRL_ACS 0x0002/* ACS Function Groups Enable */ #define PCI_ARI_CTRL_FG (x) (((x) >> 4) & 7)/* Function Group */ +/* Single Root I/O Virtualization */ +#define PCI_IOV_CAP 0x04/* SR-IOV Capabilities */ +#define PCI_IOV_CTRL 0x08/* SR-IOV Control */ +#define PCI_IOV_CTRL_VFE 0x01/* VF Enable */ +#define PCI_IOV_CTRL_MSE 0x08/* VF Memory Space Enable */ +#define PCI_IOV_CTRL_ARI 0x10/* ARI Capable Hierarchy */ +#define PCI_IOV_STATUS 0x0a/* SR-IOV Status */ +#define PCI_IOV_INITIAL_VF 0x0c/* Initial VFs */ +#define PCI_IOV_TOTAL_VF 0x0e/* Total VFs */ +#define PCI_IOV_NUM_VF 0x10/* Number of VFs */ +#define PCI_IOV_FUNC_LINK 0x12/* Function Dependency Link */ +#define PCI_IOV_VF_OFFSET 0x14/* First VF Offset */ +#define PCI_IOV_VF_STRIDE 0x16/* Following VF Stride */ +#define PCI_IOV_VF_DID 0x1a/* VF Device ID */ +#define PCI_IOV_SUP_PGSIZE 0x1c/* Supported Page Sizes */ +#define PCI_IOV_SYS_PGSIZE 0x20/* System Page Size */ +#define PCI_IOV_BAR_0 0x24/* VF BAR0 */ +#define PCI_IOV_NUM_BAR 6/* Number of VF BARs */ +#endif /* LINUX_PCI_REGS_H */
Signature · 1 line
1.5.6.4
Re: [PATCH 6/8 v4] PCI: support the SR-IOV capability
Quoted 23 lines · Yu Zhao
+++
b/drivers/pci/pci.hdrivers/pci/pci.h +17
-0@@ -176,4 +176,59 @@ static inline int pci_ari_enabled(struct pci_dev *dev) +struct pci_iov { +int cap;/* capability position */ +int align;/* page size used to map memory space */ +int is_enabled;/* status of SR-IOV */ +int nentries;/* number of sysfs entries used by PF driver */ +u16 totalvfs;/* total VFs associated with the PF */ +u16 initialvfs;/* initial VFs associated with the PF */ +u16 numvfs;/* number of VFs available */ +u16 offset;/* first VF Routing ID offset */ +u16 stride;/* following VF stride */ +struct mutex mutex;/* lock for SR-IOV */ +struct kobject kobj;/* koject for IOV */ +struct pci_dev *dev;/* Physical Function */ +struct vf_entry *ve;/* Virtual Function related */ +int (*notify)(struct pci_dev *,u32 );/* event callback function */ +}; +++ b/include/linux/pci.h@@ -87,6 +87,12 @@ enum {/* #6: expansion ROM */ PCI_ROM_RESOURCE,
drivers/pci/pci.h enum { · line 98
Quoted 10 lines
drivers/pci/pci.h +6
-0+/* device specific resources */ +#ifdef CONFIG_PCI_IOV + PCI_IOV_RESOURCES, + PCI_IOV_RESOURCES_END = PCI_IOV_RESOURCES + PCI_IOV_NUM_BAR - 1, +#endif +/* address space assigned to buses behind the bridge */ #ifndef PCI_BRIDGE_RES_NUM #define PCI_BRIDGE_RES_NUM 4
Why expand the number of resources in struct pci_dev instead of putting the new resources in struct pci_iov?
Signature · 4 lines
Matthew Wilcox Intel Open Source Technology Centre "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step."
Re: [PATCH 6/8 v4] PCI: support the SR-IOV capability
Quoted 6 lines · Matthew Wilcox
Quoted 5 lines · Yu Zhao
+++
b/include/linux/pci.hinclude/linux/pci.h +0
-0@@ -87,6 +87,12 @@ enum {/* #6: expansion ROM */ PCI_ROM_RESOURCE,
Quoted 12 lines
include/linux/pci.h enum { · line 98
Quoted 9 lines
include/linux/pci.h +6
-0+/* device specific resources */ +#ifdef CONFIG_PCI_IOV + PCI_IOV_RESOURCES, + PCI_IOV_RESOURCES_END = PCI_IOV_RESOURCES + PCI_IOV_NUM_BAR - 1, +#endif +/* address space assigned to buses behind the bridge */ #ifndef PCI_BRIDGE_RES_NUM #define PCI_BRIDGE_RES_NUM 4Why expand the number of resources in struct
pci_devinstead of putting the new resources in structpci_iov?
Yes, it's supposed to be in the 'struct pci_iov', and the resources used to be there in early version. But later I found all resource related functions such as pci_assign_resource, pdev_sort_resources, pbus_size_mem, etc. assume the resources are bundled with 'struct pci_dev' and address them using their indexes. Encapsulating resources into 'pci_iov' will impact all these functions. And I think we can postpone the change of these functions until the PCIM comes out, if the IOV is the only one who uses non-standard resources.
Quoted 6 lines
--
Matthew Wilcox Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step."
Re: [PATCH 6/8 v4] PCI: support the SR-IOV capability
In reply to Matthew WilcoxQuoted 6 lines · Matthew Wilcox
Quoted 5 lines · Yu Zhao
+++
b/include/linux/pci.hinclude/linux/pci.h +0
-0@@ -87,6 +87,12 @@ enum {/* #6: expansion ROM */ PCI_ROM_RESOURCE,
Quoted 12 lines
include/linux/pci.h enum { · line 98
Quoted 9 lines
include/linux/pci.h +6
-0+/* device specific resources */ +#ifdef CONFIG_PCI_IOV + PCI_IOV_RESOURCES, + PCI_IOV_RESOURCES_END = PCI_IOV_RESOURCES + PCI_IOV_NUM_BAR - 1, +#endif +/* address space assigned to buses behind the bridge */ #ifndef PCI_BRIDGE_RES_NUM #define PCI_BRIDGE_RES_NUM 4Why expand the number of resources in struct
pci_devinstead of putting the new resources in structpci_iov?
Yes, it's supposed to be in the 'struct pci_iov', and the resources used to be there in early version. But later I found all resource related functions such as pci_assign_resource, pdev_sort_resources, pbus_size_mem, etc. assume the resources are bundled with 'struct pci_dev' and address them using their indexes. Encapsulating resources into 'pci_iov' will impact all these functions. And I think we can postpone the change of these functions until the PCIM comes out, if the IOV is the only one who uses non-standard resources.
Quoted 6 lines
--
Matthew Wilcox Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step."
Re: [PATCH 6/8 v4] PCI: support the SR-IOV capability
In reply to Yu ZhaoQuoted 23 lines · Yu Zhao
+++
b/drivers/pci/pci.hdrivers/pci/pci.h +17
-0@@ -176,4 +176,59 @@ static inline int pci_ari_enabled(struct pci_dev *dev) +struct pci_iov { +int cap;/* capability position */ +int align;/* page size used to map memory space */ +int is_enabled;/* status of SR-IOV */ +int nentries;/* number of sysfs entries used by PF driver */ +u16 totalvfs;/* total VFs associated with the PF */ +u16 initialvfs;/* initial VFs associated with the PF */ +u16 numvfs;/* number of VFs available */ +u16 offset;/* first VF Routing ID offset */ +u16 stride;/* following VF stride */ +struct mutex mutex;/* lock for SR-IOV */ +struct kobject kobj;/* koject for IOV */ +struct pci_dev *dev;/* Physical Function */ +struct vf_entry *ve;/* Virtual Function related */ +int (*notify)(struct pci_dev *,u32 );/* event callback function */ +}; +++ b/include/linux/pci.h@@ -87,6 +87,12 @@ enum {/* #6: expansion ROM */ PCI_ROM_RESOURCE,
drivers/pci/pci.h enum { · line 98
Quoted 10 lines
drivers/pci/pci.h +6
-0+/* device specific resources */ +#ifdef CONFIG_PCI_IOV + PCI_IOV_RESOURCES, + PCI_IOV_RESOURCES_END = PCI_IOV_RESOURCES + PCI_IOV_NUM_BAR - 1, +#endif +/* address space assigned to buses behind the bridge */ #ifndef PCI_BRIDGE_RES_NUM #define PCI_BRIDGE_RES_NUM 4
Why expand the number of resources in struct pci_dev instead of putting the new resources in struct pci_iov?
Signature · 4 lines
Matthew Wilcox Intel Open Source Technology Centre "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step."
Re: [PATCH 6/8 v4] PCI: support the SR-IOV capability
In reply to Yu Zhaodrivers/pci/pci.h static inline int pci_ari_enabled(struct pci_dev *dev) · line 195
Quoted 12 lines · Yu Zhao
drivers/pci/pci.h +12
-0+struct pci_iov { +int cap;/* capability position */ +int align;/* page size used to map memory space */ +int is_enabled;/* status of SR-IOV */ +int nentries;/* number of sysfs entries used by PF driver */ +u16 totalvfs;/* total VFs associated with the PF */ +u16 initialvfs;/* initial VFs associated with the PF */ +u16 numvfs;/* number of VFs available */ +u16 offset;/* first VF Routing ID offset */ +u16 stride;/* following VF stride */ +struct mutex mutex;/* lock for SR-IOV */ +struct kobject kobj;/* koject for IOV */
Why isn't this a real struct device?
That way you get all of the proper userspace notification and the like, with kobjects, you do not.
thanks,
greg k-h
Re: [PATCH 6/8 v4] PCI: support the SR-IOV capability
In reply to Yu Zhaodrivers/pci/pci.h static inline int pci_ari_enabled(struct pci_dev *dev) · line 195
Quoted 12 lines · Yu Zhao
drivers/pci/pci.h +12
-0+struct pci_iov { +int cap;/* capability position */ +int align;/* page size used to map memory space */ +int is_enabled;/* status of SR-IOV */ +int nentries;/* number of sysfs entries used by PF driver */ +u16 totalvfs;/* total VFs associated with the PF */ +u16 initialvfs;/* initial VFs associated with the PF */ +u16 numvfs;/* number of VFs available */ +u16 offset;/* first VF Routing ID offset */ +u16 stride;/* following VF stride */ +struct mutex mutex;/* lock for SR-IOV */ +struct kobject kobj;/* koject for IOV */
Why isn't this a real struct device?
That way you get all of the proper userspace notification and the like, with kobjects, you do not.
thanks,
greg k-h
PATCH v4 7/8 PCI: reserve bus range for the SR-IOV device
In reply to Yu ZhaoReserve bus range for SR-IOV at device scanning stage.
--- drivers/pci/iov.c | 24 ++++++++++++++++++++++++ drivers/pci/pci.h | 5 +++++ drivers/pci/probe.c | 3 +++ 3 files changed, 32 insertions(+), 0 deletions(-)
drivers/pci/iov.c +24 -0
@@ -603,6 +603,30 @@ void pci_iov_remove_sysfs(struct pci_dev *dev)kfree (iov->ve); } +/** +* pci_iov_bus_range - find bus range used by SR-IOV capability +* @bus: the PCI bus +* +* Returns max number of buses (exclude current one) used by Virtual +* Functions. +*/ +int pci_iov_bus_range (struct pci_bus *bus) +{ +int max =0 ; +u8 busnr, devfn; +struct pci_dev *dev; + +list_for_each_entry (dev, &bus->devices, bus_list) { +if (!dev->iov) +continue ; +vf_rid (dev, dev->iov->totalvfs -1 , &busnr, &devfn); +if (busnr > max) + max = busnr; + } + +return max ? max - bus->number :0 ; +} +int pci_iov_resource_align (struct pci_dev *dev,int resno) {if (resno <PCI_IOV_RESOURCES || resno >PCI_IOV_RESOURCES_END )
drivers/pci/pci.h +5 -0
@@ -206,6 +206,7 @@ void pci_iov_remove_sysfs(struct pci_dev *dev);extern int pci_iov_resource_align (struct pci_dev *dev,int resno);extern int pci_iov_resource_bar (struct pci_dev *dev,int resno,enum pci_bar_type *type); +extern int pci_iov_bus_range (struct pci_bus *bus);#else static inline int pci_iov_init (struct pci_dev *dev) {
@@ -229,6 +230,10 @@ static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno, {return 0 ; } +extern inline int pci_iov_bus_range (struct pci_bus *bus) +{ +return 0 ; +}#endif /* CONFIG_PCI_IOV */ #endif /* DRIVERS_PCI_H */
drivers/pci/probe.c +3 -0
@@ -1129,6 +1129,9 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)for (devfn =0 ; devfn <0x100 ; devfn +=8 )pci_scan_slot (bus, devfn); +/* Reserve buses for SR-IOV capability. */ + max +=pci_iov_bus_range (bus); +/* * After performing arch-dependent fixup of the bus, look behind * all PCI-to-PCI bridges on this bus.
Signature · 1 line
1.5.6.4
PATCH v4 7/8 PCI: reserve bus range for the SR-IOV device
In reply to Yu ZhaoReserve bus range for SR-IOV at device scanning stage.
--- drivers/pci/iov.c | 24 ++++++++++++++++++++++++ drivers/pci/pci.h | 5 +++++ drivers/pci/probe.c | 3 +++ 3 files changed, 32 insertions(+), 0 deletions(-)
drivers/pci/iov.c +24 -0
@@ -603,6 +603,30 @@ void pci_iov_remove_sysfs(struct pci_dev *dev)kfree (iov->ve); } +/** +* pci_iov_bus_range - find bus range used by SR-IOV capability +* @bus: the PCI bus +* +* Returns max number of buses (exclude current one) used by Virtual +* Functions. +*/ +int pci_iov_bus_range (struct pci_bus *bus) +{ +int max =0 ; +u8 busnr, devfn; +struct pci_dev *dev; + +list_for_each_entry (dev, &bus->devices, bus_list) { +if (!dev->iov) +continue ; +vf_rid (dev, dev->iov->totalvfs -1 , &busnr, &devfn); +if (busnr > max) + max = busnr; + } + +return max ? max - bus->number :0 ; +} +int pci_iov_resource_align (struct pci_dev *dev,int resno) {if (resno <PCI_IOV_RESOURCES || resno >PCI_IOV_RESOURCES_END )
drivers/pci/pci.h +5 -0
@@ -206,6 +206,7 @@ void pci_iov_remove_sysfs(struct pci_dev *dev);extern int pci_iov_resource_align (struct pci_dev *dev,int resno);extern int pci_iov_resource_bar (struct pci_dev *dev,int resno,enum pci_bar_type *type); +extern int pci_iov_bus_range (struct pci_bus *bus);#else static inline int pci_iov_init (struct pci_dev *dev) {
@@ -229,6 +230,10 @@ static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno, {return 0 ; } +extern inline int pci_iov_bus_range (struct pci_bus *bus) +{ +return 0 ; +}#endif /* CONFIG_PCI_IOV */ #endif /* DRIVERS_PCI_H */
drivers/pci/probe.c +3 -0
@@ -1129,6 +1129,9 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)for (devfn =0 ; devfn <0x100 ; devfn +=8 )pci_scan_slot (bus, devfn); +/* Reserve buses for SR-IOV capability. */ + max +=pci_iov_bus_range (bus); +/* * After performing arch-dependent fixup of the bus, look behind * all PCI-to-PCI bridges on this bus.
Signature · 1 line
1.5.6.4
PATCH v4 8/8 PCI: document the changes
In reply to Yu ZhaoCreate how-to for SR-IOV user and device driver developer.
--- Documentation/DocBook/kernel-api.tmpl | 1 + Documentation/PCI/pci-iov-howto.txt | 222 +++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+), 0 deletions(-) create mode 100644 Documentation/PCI/pci-iov-howto.txt
Documentation/DocBook/kernel-api.tmpl +1 -0
@@ -251,6 +251,7 @@ X!Edrivers/pci/hotplug.c --> !Edrivers/pci/probe.c !Edrivers/pci/rom.c +!Edrivers/pci/iov.c </sect1> <sect1><title>PCI Hotplug Support Library</title> !Edrivers/pci/hotplug/pci_hotplug_core.c
Documentation/PCI/pci-iov-howto.txt new file +222 -0
222 lines not on this page · raw message
Signature · 1 line
1.5.6.4
Re: [PATCH 8/8 v4] PCI: document the changes
Hi!
Quoted 16 lines
Create how-to for SR-IOV user and device driver developer.
Signed-off-by Yu Zhao <[email protected]>+1.1 What is SR-IOV
Documentation/PCI/pci-iov-howto.txt new file +11
-0+ +Single Root I/O Virtualization (SR-IOV) is a PCI Express Extended +capability which makes one physical device appear as multiple virtual +devices. The physical device is referred to as Physical Function while +the virtual devices are referred to as Virtual Functions. Allocation +of Virtual Functions can be dynamically controlled by Physical Function +via registers encapsulated in the capability. By default, this feature +is not enabled and the Physical Function behaves as traditional PCIe +device. Once it's turned on, each Virtual Function's PCI configuration +space can be accessed by its own Bus, Device and Function Number (Routing +ID). And each Virtual Function also has PCI Memory Space, which is
Quoted 1 line
used
Ok, why is this optional? If intel cares about virtualization, it should enable this by default. I dont see why this should be configurable.
Documentation/PCI/pci-iov-howto.txt line 193
Quoted 8 lines
Documentation/PCI/pci-iov-howto.txt new file +8
-0+#ifdef CONFIG_PM +/* + * If Physical Function supports the power management, then the + * SR-IOV needs to be disabled before the adapter goes to sleep, + * because Virtual Functions will not work when the adapter is in + * the power-saving mode. + * The SR-IOV can be enabled again after the adapter wakes up. + */
How beatiful :-(.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 8/8 v4] PCI: document the changes
In reply to Yu ZhaoHi!
Quoted 16 lines
Create how-to for SR-IOV user and device driver developer.
Signed-off-by Yu Zhao <[email protected]>+1.1 What is SR-IOV
Documentation/PCI/pci-iov-howto.txt new file +11
-0+ +Single Root I/O Virtualization (SR-IOV) is a PCI Express Extended +capability which makes one physical device appear as multiple virtual +devices. The physical device is referred to as Physical Function while +the virtual devices are referred to as Virtual Functions. Allocation +of Virtual Functions can be dynamically controlled by Physical Function +via registers encapsulated in the capability. By default, this feature +is not enabled and the Physical Function behaves as traditional PCIe +device. Once it's turned on, each Virtual Function's PCI configuration +space can be accessed by its own Bus, Device and Function Number (Routing +ID). And each Virtual Function also has PCI Memory Space, which is
Quoted 1 line
used
Ok, why is this optional? If intel cares about virtualization, it should enable this by default. I dont see why this should be configurable.
Documentation/PCI/pci-iov-howto.txt line 193
Quoted 8 lines
Documentation/PCI/pci-iov-howto.txt new file +8
-0+#ifdef CONFIG_PM +/* + * If Physical Function supports the power management, then the + * SR-IOV needs to be disabled before the adapter goes to sleep, + * because Virtual Functions will not work when the adapter is in + * the power-saving mode. + * The SR-IOV can be enabled again after the adapter wakes up. + */
How beatiful :-(.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
PATCH v4 8/8 PCI: document the changes
In reply to Yu ZhaoCreate how-to for SR-IOV user and device driver developer.
--- Documentation/DocBook/kernel-api.tmpl | 1 + Documentation/PCI/pci-iov-howto.txt | 222 +++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+), 0 deletions(-) create mode 100644 Documentation/PCI/pci-iov-howto.txt
Documentation/DocBook/kernel-api.tmpl +1 -0
@@ -251,6 +251,7 @@ X!Edrivers/pci/hotplug.c --> !Edrivers/pci/probe.c !Edrivers/pci/rom.c +!Edrivers/pci/iov.c </sect1> <sect1><title>PCI Hotplug Support Library</title> !Edrivers/pci/hotplug/pci_hotplug_core.c
Documentation/PCI/pci-iov-howto.txt new file +222 -0
222 lines not on this page · raw message
Signature · 1 line
1.5.6.4