In original design, it tries to group VFs to enable more number of VFs in the
system, when VF BAR is bigger than 64MB. This design has a flaw in which one
error on a VF will interfere other VFs in the same group.
This patch series change this design by using M64 BAR in Single PE mode to
cover only one VF BAR. By doing so, it gives absolute isolation between VFs.
v3:
* return -ENOSPC when a VF has non-64bit prefetchable BAR
* rename offset to pe_num_map and define it statically
* change commit log based on comments
* define m64_map statically
v2:
* clean up iov bar alignment calculation
* change m64s to m64_bars
* add a field to represent M64 Single PE mode will be used
* change m64_wins to m64_map
* calculate the gate instead of hard coded
* dynamically allocate m64_map
* dynamically allocate PE#
* add a case to calculate iov bar alignment when M64 Single PE is used
* when M64 Single PE is used, compare num_vfs with M64 BAR available number
in system at first
Wei Yang (6):
powerpc/powernv: don't enable SRIOV when VF BAR has non
64bit-prefetchable BAR
powerpc/powernv: simplify the calculation of iov resource alignment
powerpc/powernv: use one M64 BAR in Single PE mode for one VF BAR
powerpc/powernv: replace the hard coded boundary with gate
powerpc/powernv: boundary the total VF BAR size instead of the
individual one
powerpc/powernv: allocate sparse PE# when using M64 BAR in Single PE
mode
arch/powerpc/include/asm/pci-bridge.h | 8 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 284 ++++++++++++++---------------
2 files changed, 139 insertions(+), 153 deletions(-)
--
1.7.9.5
The alignment of IOV BAR on PowerNV platform is the total size of the IOV
BAR. No matter whether the IOV BAR is extended with number of
roundup_pow_of_two(total_vfs) or number of max PE number (256), the total
size could be calculated by (vfs_expanded * VF_BAR_size).
This patch simplifies the pnv_pci_iov_resource_alignment() by removing the
first case.
Signed-off-by: Wei Yang <redacted>
Reviewed-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
On PHB_IODA2, we enable SRIOV devices by mapping IOV BAR with M64 BARs. If
a SRIOV device's IOV BAR is not 64bit-prefetchable, this is not assigned
from 64bit prefetchable window, which means M64 BAR can't work on it.
This patch makes this explicit.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 25 +++++++++----------------
1 file changed, 9 insertions(+), 16 deletions(-)
@@ -1510,6 +1501,12 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)pdn=pci_get_pdn(pdev);if(phb->type==PNV_PHB_IODA2){+if(!pdn->vfs_expanded){+dev_info(&pdev->dev,"don't support this SRIOV device"+" with non 64bit-prefetchable IOV BAR\n");+return-ENOSPC;+}+/* Calculate available PE for required VFs */mutex_lock(&phb->ioda.pe_alloc_mutex);pdn->offset=bitmap_find_next_zero_area(
@@ -2774,9 +2771,10 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)if(!res->flags||res->parent)continue;if(!pnv_pci_is_mem_pref_64(res->flags)){-dev_warn(&pdev->dev," non M64 VF BAR%d: %pR\n",+dev_warn(&pdev->dev,"Don't support SR-IOV with"+" non M64 VF BAR%d: %pR. \n",i,res);-continue;+return;}size=pci_iov_resource_size(pdev,i+PCI_IOV_RESOURCES);
In current implementation, when VF BAR is bigger than 64MB, it uses 4 M64
BARs in Single PE mode to cover the number of VFs required to be enabled.
By doing so, several VFs would be in one VF Group and leads to interference
between VFs in the same group.
This patch changes the design by using one M64 BAR in Single PE mode for
one VF BAR. This gives absolute isolation for VFs.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 6 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 163 +++++++++++------------------
2 files changed, 62 insertions(+), 107 deletions(-)
@@ -214,10 +215,9 @@ struct pci_dn {u16vfs_expanded;/* number of VFs IOV BAR expanded */u16num_vfs;/* number of VFs enabled*/intoffset;/* PE# for the first VF PE */-#define M64_PER_IOV 4-intm64_per_iov;+boolm64_single_mode;/* Use M64 BAR in Single Mode */#define IODA_INVALID_M64 (-1)-intm64_wins[PCI_SRIOV_NUM_BARS][M64_PER_IOV];+intm64_map[PCI_SRIOV_NUM_BARS][MAX_M64_BAR];#endif /* CONFIG_PCI_IOV */#endifstructlist_headchild_list;
@@ -1196,26 +1194,23 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs)pdn=pci_get_pdn(pdev);total_vfs=pci_sriov_get_totalvfs(pdev);-/* Initialize the m64_wins to IODA_INVALID_M64 */-for(i=0;i<PCI_SRIOV_NUM_BARS;i++)-for(j=0;j<M64_PER_IOV;j++)-pdn->m64_wins[i][j]=IODA_INVALID_M64;+if(pdn->m64_single_mode)+m64_bars=num_vfs;+else+m64_bars=1;++/* Initialize the m64_map to IODA_INVALID_M64 */+for(i=0;i<PCI_SRIOV_NUM_BARS;i++)+for(j=0;j<MAX_M64_BAR;j++)+pdn->m64_map[i][j]=IODA_INVALID_M64;-if(pdn->m64_per_iov==M64_PER_IOV){-vf_groups=(num_vfs<=M64_PER_IOV)?num_vfs:M64_PER_IOV;-vf_per_group=(num_vfs<=M64_PER_IOV)?1:-roundup_pow_of_two(num_vfs)/pdn->m64_per_iov;-}else{-vf_groups=1;-vf_per_group=1;-}for(i=0;i<PCI_SRIOV_NUM_BARS;i++){res=&pdev->resource[i+PCI_IOV_RESOURCES];if(!res->flags||!res->parent)continue;-for(j=0;j<vf_groups;j++){+for(j=0;j<m64_bars;j++){do{win=find_next_zero_bit(&phb->ioda.m64_bar_alloc,phb->ioda.m64_bar_idx+1,0);
@@ -1454,37 +1416,6 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs)pnv_pci_ioda2_setup_dma_pe(phb,pe);}--if(pdn->m64_per_iov==M64_PER_IOV&&num_vfs>M64_PER_IOV){-intvf_group;-intvf_per_group;-intvf_index1;--vf_per_group=roundup_pow_of_two(num_vfs)/pdn->m64_per_iov;--for(vf_group=0;vf_group<M64_PER_IOV;vf_group++){-for(vf_index=vf_group*vf_per_group;-vf_index<(vf_group+1)*vf_per_group&&-vf_index<num_vfs;-vf_index++){-for(vf_index1=vf_group*vf_per_group;-vf_index1<(vf_group+1)*vf_per_group&&-vf_index1<num_vfs;-vf_index1++){--rc=opal_pci_set_peltv(phb->opal_id,-pdn->offset+vf_index,-pdn->offset+vf_index1,-OPAL_ADD_PE_TO_DOMAIN);--if(rc)-dev_warn(&pdev->dev,"%s: Failed to link same group PE#%d(%lld)\n",-__func__,-pdn->offset+vf_index1,rc);-}-}-}-}}intpnv_pci_sriov_enable(structpci_dev*pdev,u16num_vfs)
@@ -1507,6 +1438,15 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)return-ENOSPC;}+/*+*WhenM64BARfunctionsinSinglePEmode,thenumberofVFs+*couldbeenabledmustbelessthanthenumberofM64BARs.+*/+if(pdn->m64_single_mode&&num_vfs>phb->ioda.m64_bar_idx){+dev_info(&pdev->dev,"Not enough M64 BAR for VFs\n");+return-EBUSY;+}+/* Calculate available PE for required VFs */mutex_lock(&phb->ioda.pe_alloc_mutex);pdn->offset=bitmap_find_next_zero_area(
@@ -1534,7 +1474,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)*theIOVBARaccordingtothePE#allocatedtotheVFs.*Otherwise,thePE#fortheVFwillconflictwithothers.*/-if(pdn->m64_per_iov==1){+if(!pdn->m64_single_mode){ret=pnv_pci_vf_resource_shift(pdev,pdn->offset);if(ret)gotom64_failed;
@@ -1567,8 +1507,7 @@ int pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)/* Allocate PCI data */add_dev_pci_data(pdev);-pnv_pci_sriov_enable(pdev,num_vfs);-return0;+returnpnv_pci_sriov_enable(pdev,num_vfs);}#endif /* CONFIG_PCI_IOV */
At the moment 64bit-prefetchable window can be maximum 64GB, which is
currently got from device tree. This means that in shared mode the maximum
supported VF BAR size is 64GB/256=256MB. While this size could exhaust the
whole 64bit-prefetchable window. This is a design decision to set a
boundary to 64MB of the VF BAR size. Since VF BAR size with 64MB would
occupy a quarter of the 64bit-prefetchable window, this is affordable.
This patch replaces magic limit of 64MB with (m64_segsize >> 1) and adds
comment to explain the reason for it.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
Each VF could have 6 BARs at most. When the total BAR size exceeds the
gate, after expanding it will also exhaust the M64 Window.
This patch limits the boundary by checking the total VF BAR size instead of
the individual BAR.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
When M64 BAR is set to Single PE mode, the PE# assigned to VF could be
sparse.
This patch restructures the patch to allocate sparse PE# for VFs when M64
BAR is set to Single PE mode.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 2 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 59 +++++++++++++++++++----------
2 files changed, 41 insertions(+), 20 deletions(-)
@@ -214,7 +214,7 @@ struct pci_dn {#ifdef CONFIG_PCI_IOVu16vfs_expanded;/* number of VFs IOV BAR expanded */u16num_vfs;/* number of VFs enabled*/-intoffset;/* PE# for the first VF PE */+intpe_num_map[MAX_M64_BAR];/* PE# for the first VF PE or array */boolm64_single_mode;/* Use M64 BAR in Single Mode */#define IODA_INVALID_M64 (-1)intm64_map[PCI_SRIOV_NUM_BARS][MAX_M64_BAR];
@@ -1350,14 +1350,17 @@ void pnv_pci_sriov_disable(struct pci_dev *pdev)if(phb->type==PNV_PHB_IODA2){if(!pdn->m64_single_mode)-pnv_pci_vf_resource_shift(pdev,-pdn->offset);+pnv_pci_vf_resource_shift(pdev,-pdn->pe_num_map[0]);/* Release M64 windows */pnv_pci_vf_release_m64(pdev);/* Release PE numbers */-bitmap_clear(phb->ioda.pe_alloc,pdn->offset,num_vfs);-pdn->offset=0;+if(pdn->m64_single_mode){+for(i=0;i<num_vfs;i++)+pnv_ioda_free_pe(phb,pdn->pe_num_map[i]);+}else+bitmap_clear(phb->ioda.pe_alloc,pdn->pe_num_map[0],num_vfs);}}
@@ -1383,7 +1386,10 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs)/* Reserve PE for each VF */for(vf_index=0;vf_index<num_vfs;vf_index++){-pe_num=pdn->offset+vf_index;+if(pdn->m64_single_mode)+pe_num=pdn->pe_num_map[vf_index];+else+pe_num=pdn->pe_num_map[0]+vf_index;pe=&phb->ioda.pe_array[pe_num];pe->pe_number=pe_num;
@@ -1425,6 +1431,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)structpnv_phb*phb;structpci_dn*pdn;intret;+u16i;bus=pdev->bus;hose=pci_bus_to_host(bus);
@@ -1448,19 +1455,30 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)}/* Calculate available PE for required VFs */-mutex_lock(&phb->ioda.pe_alloc_mutex);-pdn->offset=bitmap_find_next_zero_area(-phb->ioda.pe_alloc,phb->ioda.total_pe,-0,num_vfs,0);-if(pdn->offset>=phb->ioda.total_pe){+if(pdn->m64_single_mode){+for(i=0;i<num_vfs;i++)+pdn->pe_num_map[i]=IODA_INVALID_PE;+for(i=0;i<num_vfs;i++){+pdn->pe_num_map[i]=pnv_ioda_alloc_pe(phb);+if(pdn->pe_num_map[i]==IODA_INVALID_PE){+ret=-EBUSY;+gotom64_failed;+}+}+}else{+mutex_lock(&phb->ioda.pe_alloc_mutex);+pdn->pe_num_map[0]=bitmap_find_next_zero_area(+phb->ioda.pe_alloc,phb->ioda.total_pe,+0,num_vfs,0);+if(pdn->pe_num_map[0]>=phb->ioda.total_pe){+mutex_unlock(&phb->ioda.pe_alloc_mutex);+dev_info(&pdev->dev,"Failed to enable VF%d\n",num_vfs);+return-EBUSY;+}+bitmap_set(phb->ioda.pe_alloc,pdn->pe_num_map[0],num_vfs);mutex_unlock(&phb->ioda.pe_alloc_mutex);-dev_info(&pdev->dev,"Failed to enable VF%d\n",num_vfs);-pdn->offset=0;-return-EBUSY;}-bitmap_set(phb->ioda.pe_alloc,pdn->offset,num_vfs);pdn->num_vfs=num_vfs;-mutex_unlock(&phb->ioda.pe_alloc_mutex);/* Assign M64 window accordingly */ret=pnv_pci_vf_assign_m64(pdev,num_vfs);
@@ -1475,7 +1493,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)*Otherwise,thePE#fortheVFwillconflictwithothers.*/if(!pdn->m64_single_mode){-ret=pnv_pci_vf_resource_shift(pdev,pdn->offset);+ret=pnv_pci_vf_resource_shift(pdev,pdn->pe_num_map[0]);if(ret)gotom64_failed;}
@@ -1487,8 +1505,11 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)return0;m64_failed:-bitmap_clear(phb->ioda.pe_alloc,pdn->offset,num_vfs);-pdn->offset=0;+if(pdn->m64_single_mode){+for(i=0;i<num_vfs;i++)+pnv_ioda_free_pe(phb,pdn->pe_num_map[i]);+}else+bitmap_clear(phb->ioda.pe_alloc,pdn->pe_num_map[0],num_vfs);returnret;}
On Thu, Aug 13, 2015 at 10:11:06PM +0800, Wei Yang wrote:
On PHB_IODA2, we enable SRIOV devices by mapping IOV BAR with M64 BARs. If
a SRIOV device's IOV BAR is not 64bit-prefetchable, this is not assigned
from 64bit prefetchable window, which means M64 BAR can't work on it.
This patch makes this explicit.
Signed-off-by: Wei Yang <redacted>
@@ -908,9 +908,6 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset)
if (!res->flags || !res->parent)
continue;
- if (!pnv_pci_is_mem_pref_64(res->flags))
- continue;
-
/*
* The actual IOV BAR range is determined by the start address
* and the actual size for num_vfs VFs BAR. This check is to
@@ -939,9 +936,6 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset)
if (!res->flags || !res->parent)
continue;
- if (!pnv_pci_is_mem_pref_64(res->flags))
- continue;
-
size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
res2 = *res;
res->start += size * offset;
if (!res->flags || !res->parent)
continue;
- if (!pnv_pci_is_mem_pref_64(res->flags))
- continue;
-
for (j = 0; j < vf_groups; j++) {
do {
win = find_next_zero_bit(&phb->ioda.m64_bar_alloc,
@@ -1510,6 +1501,12 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
pdn = pci_get_pdn(pdev);
if (phb->type == PNV_PHB_IODA2) {
+ if (!pdn->vfs_expanded) {
+ dev_info(&pdev->dev, "don't support this SRIOV device"
+ " with non 64bit-prefetchable IOV BAR\n");
+ return -ENOSPC;
+ }
+
/* Calculate available PE for required VFs */
mutex_lock(&phb->ioda.pe_alloc_mutex);
pdn->offset = bitmap_find_next_zero_area(
On Thu, Aug 13, 2015 at 10:11:08PM +0800, Wei Yang wrote:
quoted hunk
In current implementation, when VF BAR is bigger than 64MB, it uses 4 M64
BARs in Single PE mode to cover the number of VFs required to be enabled.
By doing so, several VFs would be in one VF Group and leads to interference
between VFs in the same group.
This patch changes the design by using one M64 BAR in Single PE mode for
one VF BAR. This gives absolute isolation for VFs.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 6 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 163 +++++++++++------------------
2 files changed, 62 insertions(+), 107 deletions(-)
@@ -187,6 +187,7 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)*/
struct iommu_table;
+#define MAX_M64_BAR 16
struct pnv_phb::m64_bar_idx is initialized to 15. Another macro is defined here
as 16. Both of them can be used as maximal M64 BAR number. Obviously, they're
duplicated. On the other hand, I don't think it's a good idea to have the static
"m64_map" because @pdn is created for every PCI devices, including VFs. non-PF
don't "m64_map", together other fields like "m64_per_iov" at all. It's obviously
wasting memory. So it would be allocated dynamically when the PF's pdn is created
or in pnv_pci_ioda_fixup_iov_resources().
In long run, it might be reasonable to move all SRIOV related fields in pci_dn
to another data struct (struct pci_iov_dn?) and allocate that dynamically.
quoted hunk
int flags;
#define PCI_DN_FLAG_IOV_VF 0x01
@@ -214,10 +215,9 @@ struct pci_dn {
u16 vfs_expanded; /* number of VFs IOV BAR expanded */
u16 num_vfs; /* number of VFs enabled*/
int offset; /* PE# for the first VF PE */
-#define M64_PER_IOV 4
- int m64_per_iov;
+ bool m64_single_mode; /* Use M64 BAR in Single Mode */
#define IODA_INVALID_M64 (-1)
- int m64_wins[PCI_SRIOV_NUM_BARS][M64_PER_IOV];
+ int m64_map[PCI_SRIOV_NUM_BARS][MAX_M64_BAR];
#endif /* CONFIG_PCI_IOV */
#endif
struct list_head child_list;
int total_vfs;
resource_size_t size, start;
int pe_num;
- int vf_groups;
- int vf_per_group;
+ int m64_bars;
bus = pdev->bus;
hose = pci_bus_to_host(bus);
pdn = pci_get_pdn(pdev);
total_vfs = pci_sriov_get_totalvfs(pdev);
- /* Initialize the m64_wins to IODA_INVALID_M64 */
- for (i = 0; i < PCI_SRIOV_NUM_BARS; i++)
- for (j = 0; j < M64_PER_IOV; j++)
- pdn->m64_wins[i][j] = IODA_INVALID_M64;
+ if (pdn->m64_single_mode)
+ m64_bars = num_vfs;
+ else
+ m64_bars = 1;
+
+ /* Initialize the m64_map to IODA_INVALID_M64 */
+ for (i = 0; i < PCI_SRIOV_NUM_BARS ; i++)
+ for (j = 0; j < MAX_M64_BAR; j++)
+ pdn->m64_map[i][j] = IODA_INVALID_M64;
It would be done in pnv_pci_ioda_fixup_iov_resources(). That means it will
be done for once if hotplug isn't considered. The code here will be called
on every attempt to enable SRIOV capability, which isn't necessary, right?
quoted hunk
- if (pdn->m64_per_iov == M64_PER_IOV) {
- vf_groups = (num_vfs <= M64_PER_IOV) ? num_vfs: M64_PER_IOV;
- vf_per_group = (num_vfs <= M64_PER_IOV)? 1:
- roundup_pow_of_two(num_vfs) / pdn->m64_per_iov;
- } else {
- vf_groups = 1;
- vf_per_group = 1;
- }
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &pdev->resource[i + PCI_IOV_RESOURCES];
if (!res->flags || !res->parent)
continue;
- for (j = 0; j < vf_groups; j++) {
+ for (j = 0; j < m64_bars; j++) {
do {
win = find_next_zero_bit(&phb->ioda.m64_bar_alloc,
phb->ioda.m64_bar_idx + 1, 0);
@@ -1507,6 +1438,15 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
return -ENOSPC;
}
+ /*
+ * When M64 BAR functions in Single PE mode, the number of VFs
+ * could be enabled must be less than the number of M64 BARs.
+ */
+ if (pdn->m64_single_mode && num_vfs > phb->ioda.m64_bar_idx) {
+ dev_info(&pdev->dev, "Not enough M64 BAR for VFs\n");
+ return -EBUSY;
+ }
s/M64 BAR/M64 BARs
quoted hunk
+
/* Calculate available PE for required VFs */
mutex_lock(&phb->ioda.pe_alloc_mutex);
pdn->offset = bitmap_find_next_zero_area(
@@ -1534,7 +1474,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
* the IOV BAR according to the PE# allocated to the VFs.
* Otherwise, the PE# for the VF will conflict with others.
*/
- if (pdn->m64_per_iov == 1) {
+ if (!pdn->m64_single_mode) {
ret = pnv_pci_vf_resource_shift(pdev, pdn->offset);
if (ret)
goto m64_failed;
@@ -1567,8 +1507,7 @@ int pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
* SR-IOV. While from hardware perspective, the range mapped by M64
* BAR should be size aligned.
*
+ * When IOV BAR is mapped with M64 BAR in Single PE mode, the extra
+ * powernv-specific hardware restriction is gone. But if just use the
+ * VF BAR size as the alignment, PF BAR / VF BAR may be allocated with
+ * in one segment of M64 #15, which introduces the PE conflict between
+ * PF and VF. Based on this, the minimum alignment of an IOV BAR is
+ * m64_segsize.
+ *
* This function return the total IOV BAR size if expanded or just the
- * individual size if not.
+ * individual size if not, when M64 BAR is in Shared PE mode.
+ * If the M64 BAR is in Single PE mode, return the VF BAR size or
+ * m64_size if IOV BAR size is less.
*/
On Thu, Aug 13, 2015 at 10:11:09PM +0800, Wei Yang wrote:
At the moment 64bit-prefetchable window can be maximum 64GB, which is
currently got from device tree. This means that in shared mode the maximum
supported VF BAR size is 64GB/256=256MB. While this size could exhaust the
whole 64bit-prefetchable window. This is a design decision to set a
boundary to 64MB of the VF BAR size. Since VF BAR size with 64MB would
occupy a quarter of the 64bit-prefetchable window, this is affordable.
This patch replaces magic limit of 64MB with (m64_segsize >> 1) and adds
comment to explain the reason for it.
Signed-off-by: Wei Yang <redacted>
total_vfs = pci_sriov_get_totalvfs(pdev);
mul = phb->ioda.total_pe;
+ /*
+ * If bigger than or equal to half of M64 segment size, just round up
+ * power of two.
+ *
+ * Generally, one M64 BAR maps one IOV BAR. To avoid conflict with
+ * other devices, IOV BAR size is expanded to be (total_pe *
+ * VF_BAR_size). When VF_BAR_size is half of M64 segment size , the
+ * expanded size would equal to half of the whole M64 Space size,
+ * which will exhaust the M64 Space and limit the system flexibility.
+ */
s/M64 Space/M64 space
quoted hunk
+ gate = phb->ioda.m64_segsize >> 1;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &pdev->resource[i + PCI_IOV_RESOURCES];
On Thu, Aug 13, 2015 at 10:11:10PM +0800, Wei Yang wrote:
Each VF could have 6 BARs at most. When the total BAR size exceeds the
gate, after expanding it will also exhaust the M64 Window.
This patch limits the boundary by checking the total VF BAR size instead of
the individual BAR.
Signed-off-by: Wei Yang <redacted>
* which will exhaust the M64 Space and limit the system flexibility.
*/
gate = phb->ioda.m64_segsize >> 1;
+ total_vf_bar_sz = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &pdev->resource[i + PCI_IOV_RESOURCES];
On Thu, Aug 13, 2015 at 10:11:11PM +0800, Wei Yang wrote:
quoted hunk
When M64 BAR is set to Single PE mode, the PE# assigned to VF could be
sparse.
This patch restructures the patch to allocate sparse PE# for VFs when M64
BAR is set to Single PE mode.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 2 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 59 +++++++++++++++++++----------
2 files changed, 41 insertions(+), 20 deletions(-)
#ifdef CONFIG_PCI_IOV
u16 vfs_expanded; /* number of VFs IOV BAR expanded */
u16 num_vfs; /* number of VFs enabled*/
- int offset; /* PE# for the first VF PE */
+ int pe_num_map[MAX_M64_BAR];/* PE# for the first VF PE or array */
Same question as to "m64_map". pdn for non-PF doesn't need it.
quoted hunk
bool m64_single_mode; /* Use M64 BAR in Single Mode */
#define IODA_INVALID_M64 (-1)
int m64_map[PCI_SRIOV_NUM_BARS][MAX_M64_BAR];
/* Reserve PE for each VF */
for (vf_index = 0; vf_index < num_vfs; vf_index++) {
- pe_num = pdn->offset + vf_index;
+ if (pdn->m64_single_mode)
+ pe_num = pdn->pe_num_map[vf_index];
+ else
+ pe_num = pdn->pe_num_map[0] + vf_index;
pe = &phb->ioda.pe_array[pe_num];
pe->pe_number = pe_num;
@@ -1425,6 +1431,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
struct pnv_phb *phb;
struct pci_dn *pdn;
int ret;
+ u16 i;
bus = pdev->bus;
hose = pci_bus_to_host(bus);
@@ -1448,19 +1455,30 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
}
/* Calculate available PE for required VFs */
- mutex_lock(&phb->ioda.pe_alloc_mutex);
- pdn->offset = bitmap_find_next_zero_area(
- phb->ioda.pe_alloc, phb->ioda.total_pe,
- 0, num_vfs, 0);
- if (pdn->offset >= phb->ioda.total_pe) {
+ if (pdn->m64_single_mode) {
+ for (i = 0; i < num_vfs; i++)
+ pdn->pe_num_map[i] = IODA_INVALID_PE;
+ for (i = 0; i < num_vfs; i++) {
+ pdn->pe_num_map[i] = pnv_ioda_alloc_pe(phb);
+ if (pdn->pe_num_map[i] == IODA_INVALID_PE) {
+ ret = -EBUSY;
+ goto m64_failed;
+ }
+ }
+ } else {
+ mutex_lock(&phb->ioda.pe_alloc_mutex);
+ pdn->pe_num_map[0] = bitmap_find_next_zero_area(
+ phb->ioda.pe_alloc, phb->ioda.total_pe,
+ 0, num_vfs, 0);
+ if (pdn->pe_num_map[0] >= phb->ioda.total_pe) {
+ mutex_unlock(&phb->ioda.pe_alloc_mutex);
+ dev_info(&pdev->dev, "Failed to enable VF%d\n", num_vfs);
+ return -EBUSY;
+ }
+ bitmap_set(phb->ioda.pe_alloc, pdn->pe_num_map[0], num_vfs);
mutex_unlock(&phb->ioda.pe_alloc_mutex);
- dev_info(&pdev->dev, "Failed to enable VF%d\n", num_vfs);
- pdn->offset = 0;
- return -EBUSY;
}
- bitmap_set(phb->ioda.pe_alloc, pdn->offset, num_vfs);
pdn->num_vfs = num_vfs;
- mutex_unlock(&phb->ioda.pe_alloc_mutex);
/* Assign M64 window accordingly */
ret = pnv_pci_vf_assign_m64(pdev, num_vfs);
@@ -1475,7 +1493,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
* Otherwise, the PE# for the VF will conflict with others.
*/
if (!pdn->m64_single_mode) {
- ret = pnv_pci_vf_resource_shift(pdev, pdn->offset);
+ ret = pnv_pci_vf_resource_shift(pdev, pdn->pe_num_map[0]);
if (ret)
goto m64_failed;
}
@@ -1487,8 +1505,11 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
return 0;
m64_failed:
- bitmap_clear(phb->ioda.pe_alloc, pdn->offset, num_vfs);
- pdn->offset = 0;
+ if (pdn->m64_single_mode) {
+ for (i = 0; i < num_vfs; i++)
+ pnv_ioda_free_pe(phb, pdn->pe_num_map[i]);
if pdn->pe_num_map[i] isn't valid PE number, what will happen?
On Thu, Aug 13, 2015 at 10:11:07PM +0800, Wei Yang wrote:
quoted hunk
The alignment of IOV BAR on PowerNV platform is the total size of the IOV
BAR. No matter whether the IOV BAR is extended with number of
roundup_pow_of_two(total_vfs) or number of max PE number (256), the total
size could be calculated by (vfs_expanded * VF_BAR_size).
This patch simplifies the pnv_pci_iov_resource_alignment() by removing the
first case.
Signed-off-by: Wei Yang <redacted>
Reviewed-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
int resno)
{
struct pci_dn *pdn = pci_get_pdn(pdev);
- resource_size_t align, iov_align;
-
- iov_align = resource_size(&pdev->resource[resno]);
- if (iov_align)
- return iov_align;
+ resource_size_t align;
+ /*
+ * On PowerNV platform, IOV BAR is mapped by M64 BAR to enable the
+ * SR-IOV. While from hardware perspective, the range mapped by M64
+ * BAR should be size aligned.
+ *
+ * This function return the total IOV BAR size if expanded or just the
+ * individual size if not.
+ */
On Fri, Aug 14, 2015 at 11:04:58AM +1000, Gavin Shan wrote:
On Thu, Aug 13, 2015 at 10:11:07PM +0800, Wei Yang wrote:
quoted
The alignment of IOV BAR on PowerNV platform is the total size of the IOV
BAR. No matter whether the IOV BAR is extended with number of
roundup_pow_of_two(total_vfs) or number of max PE number (256), the total
size could be calculated by (vfs_expanded * VF_BAR_size).
This patch simplifies the pnv_pci_iov_resource_alignment() by removing the
first case.
Signed-off-by: Wei Yang <redacted>
Reviewed-by: Gavin Shan <redacted>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
int resno)
{
struct pci_dn *pdn = pci_get_pdn(pdev);
- resource_size_t align, iov_align;
-
- iov_align = resource_size(&pdev->resource[resno]);
- if (iov_align)
- return iov_align;
+ resource_size_t align;
+ /*
+ * On PowerNV platform, IOV BAR is mapped by M64 BAR to enable the
+ * SR-IOV. While from hardware perspective, the range mapped by M64
+ * BAR should be size aligned.
+ *
+ * This function return the total IOV BAR size if expanded or just the
+ * individual size if not.
+ */
On Fri, Aug 14, 2015 at 10:52:21AM +1000, Gavin Shan wrote:
On Thu, Aug 13, 2015 at 10:11:08PM +0800, Wei Yang wrote:
quoted
In current implementation, when VF BAR is bigger than 64MB, it uses 4 M64
BARs in Single PE mode to cover the number of VFs required to be enabled.
By doing so, several VFs would be in one VF Group and leads to interference
between VFs in the same group.
This patch changes the design by using one M64 BAR in Single PE mode for
one VF BAR. This gives absolute isolation for VFs.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 6 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 163 +++++++++++------------------
2 files changed, 62 insertions(+), 107 deletions(-)
@@ -187,6 +187,7 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)*/
struct iommu_table;
+#define MAX_M64_BAR 16
struct pnv_phb::m64_bar_idx is initialized to 15. Another macro is defined here
as 16. Both of them can be used as maximal M64 BAR number. Obviously, they're
duplicated. On the other hand, I don't think it's a good idea to have the static
"m64_map" because @pdn is created for every PCI devices, including VFs. non-PF
don't "m64_map", together other fields like "m64_per_iov" at all. It's obviously
wasting memory. So it would be allocated dynamically when the PF's pdn is created
or in pnv_pci_ioda_fixup_iov_resources().
I prefer the dynamic one.
Alexey,
I changed to static defined based on your comments. So do you have some
concern on the dynamic version?
In long run, it might be reasonable to move all SRIOV related fields in pci_dn
to another data struct (struct pci_iov_dn?) and allocate that dynamically.
quoted
int flags;
#define PCI_DN_FLAG_IOV_VF 0x01
@@ -214,10 +215,9 @@ struct pci_dn {
u16 vfs_expanded; /* number of VFs IOV BAR expanded */
u16 num_vfs; /* number of VFs enabled*/
int offset; /* PE# for the first VF PE */
-#define M64_PER_IOV 4
- int m64_per_iov;
+ bool m64_single_mode; /* Use M64 BAR in Single Mode */
#define IODA_INVALID_M64 (-1)
- int m64_wins[PCI_SRIOV_NUM_BARS][M64_PER_IOV];
+ int m64_map[PCI_SRIOV_NUM_BARS][MAX_M64_BAR];
#endif /* CONFIG_PCI_IOV */
#endif
struct list_head child_list;
int total_vfs;
resource_size_t size, start;
int pe_num;
- int vf_groups;
- int vf_per_group;
+ int m64_bars;
bus = pdev->bus;
hose = pci_bus_to_host(bus);
pdn = pci_get_pdn(pdev);
total_vfs = pci_sriov_get_totalvfs(pdev);
- /* Initialize the m64_wins to IODA_INVALID_M64 */
- for (i = 0; i < PCI_SRIOV_NUM_BARS; i++)
- for (j = 0; j < M64_PER_IOV; j++)
- pdn->m64_wins[i][j] = IODA_INVALID_M64;
+ if (pdn->m64_single_mode)
+ m64_bars = num_vfs;
+ else
+ m64_bars = 1;
+
+ /* Initialize the m64_map to IODA_INVALID_M64 */
+ for (i = 0; i < PCI_SRIOV_NUM_BARS ; i++)
+ for (j = 0; j < MAX_M64_BAR; j++)
+ pdn->m64_map[i][j] = IODA_INVALID_M64;
It would be done in pnv_pci_ioda_fixup_iov_resources(). That means it will
be done for once if hotplug isn't considered. The code here will be called
on every attempt to enable SRIOV capability, which isn't necessary, right?
I think you are right.
--
Richard Yang
Help you, Help me
On Fri, Aug 14, 2015 at 11:03:00AM +1000, Gavin Shan wrote:
On Thu, Aug 13, 2015 at 10:11:11PM +0800, Wei Yang wrote:
quoted
When M64 BAR is set to Single PE mode, the PE# assigned to VF could be
sparse.
This patch restructures the patch to allocate sparse PE# for VFs when M64
BAR is set to Single PE mode.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 2 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 59 +++++++++++++++++++----------
2 files changed, 41 insertions(+), 20 deletions(-)
#ifdef CONFIG_PCI_IOV
u16 vfs_expanded; /* number of VFs IOV BAR expanded */
u16 num_vfs; /* number of VFs enabled*/
- int offset; /* PE# for the first VF PE */
+ int pe_num_map[MAX_M64_BAR];/* PE# for the first VF PE or array */
Same question as to "m64_map". pdn for non-PF doesn't need it.
The same, I prefer the dynamic version.
quoted
bool m64_single_mode; /* Use M64 BAR in Single Mode */
#define IODA_INVALID_M64 (-1)
int m64_map[PCI_SRIOV_NUM_BARS][MAX_M64_BAR];
/* Reserve PE for each VF */
for (vf_index = 0; vf_index < num_vfs; vf_index++) {
- pe_num = pdn->offset + vf_index;
+ if (pdn->m64_single_mode)
+ pe_num = pdn->pe_num_map[vf_index];
+ else
+ pe_num = pdn->pe_num_map[0] + vf_index;
pe = &phb->ioda.pe_array[pe_num];
pe->pe_number = pe_num;
@@ -1425,6 +1431,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
struct pnv_phb *phb;
struct pci_dn *pdn;
int ret;
+ u16 i;
bus = pdev->bus;
hose = pci_bus_to_host(bus);
@@ -1448,19 +1455,30 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
}
/* Calculate available PE for required VFs */
- mutex_lock(&phb->ioda.pe_alloc_mutex);
- pdn->offset = bitmap_find_next_zero_area(
- phb->ioda.pe_alloc, phb->ioda.total_pe,
- 0, num_vfs, 0);
- if (pdn->offset >= phb->ioda.total_pe) {
+ if (pdn->m64_single_mode) {
+ for (i = 0; i < num_vfs; i++)
+ pdn->pe_num_map[i] = IODA_INVALID_PE;
+ for (i = 0; i < num_vfs; i++) {
+ pdn->pe_num_map[i] = pnv_ioda_alloc_pe(phb);
+ if (pdn->pe_num_map[i] == IODA_INVALID_PE) {
+ ret = -EBUSY;
+ goto m64_failed;
+ }
+ }
+ } else {
+ mutex_lock(&phb->ioda.pe_alloc_mutex);
+ pdn->pe_num_map[0] = bitmap_find_next_zero_area(
+ phb->ioda.pe_alloc, phb->ioda.total_pe,
+ 0, num_vfs, 0);
+ if (pdn->pe_num_map[0] >= phb->ioda.total_pe) {
+ mutex_unlock(&phb->ioda.pe_alloc_mutex);
+ dev_info(&pdev->dev, "Failed to enable VF%d\n", num_vfs);
+ return -EBUSY;
+ }
+ bitmap_set(phb->ioda.pe_alloc, pdn->pe_num_map[0], num_vfs);
mutex_unlock(&phb->ioda.pe_alloc_mutex);
- dev_info(&pdev->dev, "Failed to enable VF%d\n", num_vfs);
- pdn->offset = 0;
- return -EBUSY;
}
- bitmap_set(phb->ioda.pe_alloc, pdn->offset, num_vfs);
pdn->num_vfs = num_vfs;
- mutex_unlock(&phb->ioda.pe_alloc_mutex);
/* Assign M64 window accordingly */
ret = pnv_pci_vf_assign_m64(pdev, num_vfs);
@@ -1475,7 +1493,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
* Otherwise, the PE# for the VF will conflict with others.
*/
if (!pdn->m64_single_mode) {
- ret = pnv_pci_vf_resource_shift(pdev, pdn->offset);
+ ret = pnv_pci_vf_resource_shift(pdev, pdn->pe_num_map[0]);
if (ret)
goto m64_failed;
}
@@ -1487,8 +1505,11 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
return 0;
m64_failed:
- bitmap_clear(phb->ioda.pe_alloc, pdn->offset, num_vfs);
- pdn->offset = 0;
+ if (pdn->m64_single_mode) {
+ for (i = 0; i < num_vfs; i++)
+ pnv_ioda_free_pe(phb, pdn->pe_num_map[i]);
if pdn->pe_num_map[i] isn't valid PE number, what will happen?
On Fri, Aug 14, 2015 at 10:52:21AM +1000, Gavin Shan wrote:
quoted
On Thu, Aug 13, 2015 at 10:11:08PM +0800, Wei Yang wrote:
quoted
In current implementation, when VF BAR is bigger than 64MB, it uses 4 M64
BARs in Single PE mode to cover the number of VFs required to be enabled.
By doing so, several VFs would be in one VF Group and leads to interference
between VFs in the same group.
This patch changes the design by using one M64 BAR in Single PE mode for
one VF BAR. This gives absolute isolation for VFs.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 6 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 163 +++++++++++------------------
2 files changed, 62 insertions(+), 107 deletions(-)
@@ -187,6 +187,7 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)*/
struct iommu_table;
+#define MAX_M64_BAR 16
struct pnv_phb::m64_bar_idx is initialized to 15. Another macro is defined here
as 16. Both of them can be used as maximal M64 BAR number. Obviously, they're
duplicated. On the other hand, I don't think it's a good idea to have the static
"m64_map" because @pdn is created for every PCI devices, including VFs. non-PF
don't "m64_map", together other fields like "m64_per_iov" at all. It's obviously
wasting memory. So it would be allocated dynamically when the PF's pdn is created
or in pnv_pci_ioda_fixup_iov_resources().
I prefer the dynamic one.
Alexey,
I changed to static defined based on your comments. So do you have some
concern on the dynamic version?
Is this map only valid for a VF and PF won't have/need one?
If so, yes, kmalloc() it.
quoted
In long run, it might be reasonable to move all SRIOV related fields in pci_dn
to another data struct (struct pci_iov_dn?) and allocate that dynamically.
quoted
int flags;
#define PCI_DN_FLAG_IOV_VF 0x01
@@ -214,10 +215,9 @@ struct pci_dn {
u16 vfs_expanded; /* number of VFs IOV BAR expanded */
u16 num_vfs; /* number of VFs enabled*/
int offset; /* PE# for the first VF PE */
-#define M64_PER_IOV 4
- int m64_per_iov;
+ bool m64_single_mode; /* Use M64 BAR in Single Mode */
#define IODA_INVALID_M64 (-1)
- int m64_wins[PCI_SRIOV_NUM_BARS][M64_PER_IOV];
+ int m64_map[PCI_SRIOV_NUM_BARS][MAX_M64_BAR];
Is not here an extra space before "m64_map"?
Also the commit log does not explain why symbols were renamed (what since
you are renaming them - say a couple of words what they are).
int total_vfs;
resource_size_t size, start;
int pe_num;
- int vf_groups;
- int vf_per_group;
+ int m64_bars;
bus = pdev->bus;
hose = pci_bus_to_host(bus);
pdn = pci_get_pdn(pdev);
total_vfs = pci_sriov_get_totalvfs(pdev);
- /* Initialize the m64_wins to IODA_INVALID_M64 */
- for (i = 0; i < PCI_SRIOV_NUM_BARS; i++)
- for (j = 0; j < M64_PER_IOV; j++)
- pdn->m64_wins[i][j] = IODA_INVALID_M64;
+ if (pdn->m64_single_mode)
+ m64_bars = num_vfs;
+ else
+ m64_bars = 1;
+
+ /* Initialize the m64_map to IODA_INVALID_M64 */
+ for (i = 0; i < PCI_SRIOV_NUM_BARS ; i++)
+ for (j = 0; j < MAX_M64_BAR; j++)
+ pdn->m64_map[i][j] = IODA_INVALID_M64;
It would be done in pnv_pci_ioda_fixup_iov_resources(). That means it will
be done for once if hotplug isn't considered. The code here will be called
on every attempt to enable SRIOV capability, which isn't necessary, right?
On Thu, Aug 13, 2015 at 10:11:10PM +0800, Wei Yang wrote:
quoted
Each VF could have 6 BARs at most. When the total BAR size exceeds the
gate, after expanding it will also exhaust the M64 Window.
This patch limits the boundary by checking the total VF BAR size instead of
the individual BAR.
Signed-off-by: Wei Yang <redacted>
* which will exhaust the M64 Space and limit the system flexibility.
*/
gate = phb->ioda.m64_segsize >> 1;
+ total_vf_bar_sz = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = &pdev->resource[i + PCI_IOV_RESOURCES];
return;
}
- size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES);
+ total_vf_bar_sz += pci_iov_resource_size(pdev,
+ i + PCI_IOV_RESOURCES);
/* bigger than or equal to gate */
- if (size >= gate) {
- dev_info(&pdev->dev, "PowerNV: VF BAR%d: %pR IOV size "
- "is bigger than %lld, roundup power2\n",
- i, res, gate);
+ if (total_vf_bar_sz >= gate) {
+ dev_info(&pdev->dev, "PowerNV: VF BAR Total IOV size "
+ "is bigger than %lld, roundup power2\n", gate);
dev_info(&pdev->dev, "PowerNV: Total VF BAR size %lld "
"is bigger than %lld, roundup power2\n",
total_vf_bar_sz, gate);
Please do not split user visible lines, the 80 chars rule does not apply
for string constants. But since we are still better not to go too far from
80 symbols, remove ", roundup power2" or make the message shorter somehow
else. Like:
dev_info(&pdev->dev,
"PowerNV: Total VF BAR size %lld > %lld, roundup to %lld\n",
total_vf_bar_sz, gate, mul);
and move it after roundup_pow_of_two() call.
And "PowerNV" prefix does not seem necessary either (it is not used very
often and even without the prefix it is quite obvious that this is powernv
and you could still grep for this message in the kernel source tree).
quoted
mul = roundup_pow_of_two(total_vfs);
pdn->m64_single_mode = true;
break;
--
1.7.9.5
At the moment 64bit-prefetchable window can be maximum 64GB, which is
currently got from device tree. This means that in shared mode the maximum
supported VF BAR size is 64GB/256=256MB. While this size could exhaust the
whole 64bit-prefetchable window. This is a design decision to set a
boundary to 64MB of the VF BAR size. Since VF BAR size with 64MB would
occupy a quarter of the 64bit-prefetchable window, this is affordable.
This patch replaces magic limit of 64MB with (m64_segsize >> 1) and adds
comment to explain the reason for it.
Having m64_segsize divided in _halves_ is also magic (or is it a "design
decision"?).
It should be:
const resource_size_t gate = phb->ioda.m64_segsize >> 1;
as it never changes in the function.
quoted hunk
struct pci_dn *pdn;
int mul, total_vfs;
@@ -2704,6 +2704,17 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) total_vfs = pci_sriov_get_totalvfs(pdev); mul = phb->ioda.total_pe;+ /*+ * If bigger than or equal to half of M64 segment size, just round up+ * power of two.+ *+ * Generally, one M64 BAR maps one IOV BAR. To avoid conflict with+ * other devices, IOV BAR size is expanded to be (total_pe *+ * VF_BAR_size). When VF_BAR_size is half of M64 segment size , the+ * expanded size would equal to half of the whole M64 Space size,+ * which will exhaust the M64 Space and limit the system flexibility.+ */+ gate = phb->ioda.m64_segsize >> 1; for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { res = &pdev->resource[i + PCI_IOV_RESOURCES];
@@ -2718,10 +2729,11 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES);- /* bigger than 64M */- if (size > (1 << 26)) {- dev_info(&pdev->dev, "PowerNV: VF BAR%d: %pR IOV size is bigger than 64M, roundup power2\n",- i, res);+ /* bigger than or equal to gate */
That multiline comment is better to be here, I think.
+ if (size >= gate) {
+ dev_info(&pdev->dev, "PowerNV: VF BAR%d: %pR IOV size "
+ "is bigger than %lld, roundup power2\n",
+ i, res, gate);
mul = roundup_pow_of_two(total_vfs);
pdn->m64_single_mode = true;
break;
On Thu, Aug 13, 2015 at 10:11:11PM +0800, Wei Yang wrote:
quoted
When M64 BAR is set to Single PE mode, the PE# assigned to VF could be
sparse.
This patch restructures the patch to allocate sparse PE# for VFs when M64
BAR is set to Single PE mode.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 2 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 59 +++++++++++++++++++----------
2 files changed, 41 insertions(+), 20 deletions(-)
#ifdef CONFIG_PCI_IOV
u16 vfs_expanded; /* number of VFs IOV BAR expanded */
u16 num_vfs; /* number of VFs enabled*/
- int offset; /* PE# for the first VF PE */
+ int pe_num_map[MAX_M64_BAR];/* PE# for the first VF PE or array */
Same question as to "m64_map". pdn for non-PF doesn't need it.
On Sat, Aug 15, 2015 at 08:27:54PM +1000, Alexey Kardashevskiy wrote:
On 08/14/2015 11:03 AM, Gavin Shan wrote:
quoted
On Thu, Aug 13, 2015 at 10:11:11PM +0800, Wei Yang wrote:
quoted
When M64 BAR is set to Single PE mode, the PE# assigned to VF could be
sparse.
This patch restructures the patch to allocate sparse PE# for VFs when M64
BAR is set to Single PE mode.
Signed-off-by: Wei Yang <redacted>
---
arch/powerpc/include/asm/pci-bridge.h | 2 +-
arch/powerpc/platforms/powernv/pci-ioda.c | 59 +++++++++++++++++++----------
2 files changed, 41 insertions(+), 20 deletions(-)
#ifdef CONFIG_PCI_IOV
u16 vfs_expanded; /* number of VFs IOV BAR expanded */
u16 num_vfs; /* number of VFs enabled*/
- int offset; /* PE# for the first VF PE */
+ int pe_num_map[MAX_M64_BAR];/* PE# for the first VF PE or array */
Same question as to "m64_map". pdn for non-PF doesn't need it.
non-PF is VF, right?
3 types of devices: (A) PF (B) VF (C) All others. Here, I mean (C).
Thanks,
Gavin
On Sat, Aug 15, 2015 at 08:27:04PM +1000, Alexey Kardashevskiy wrote:
On 08/14/2015 12:11 AM, Wei Yang wrote:
quoted
At the moment 64bit-prefetchable window can be maximum 64GB, which is
currently got from device tree. This means that in shared mode the maximum
supported VF BAR size is 64GB/256=256MB. While this size could exhaust the
whole 64bit-prefetchable window. This is a design decision to set a
boundary to 64MB of the VF BAR size. Since VF BAR size with 64MB would
occupy a quarter of the 64bit-prefetchable window, this is affordable.
This patch replaces magic limit of 64MB with (m64_segsize >> 1) and adds
comment to explain the reason for it.
Having m64_segsize divided in _halves_ is also magic (or is it a
"design decision"?).
Hmm... as the last sentence in previous paragraph said, 64MB VF BAR would
occupy a quarter of the 64bit-prefetchable window which is affordable.
Maybe I could change to this:
This patch replaces magic limit of 64MB with "gate", which is 1/4 of the
M64 Segment Size(m64_segsize >> 2) and adds comment to explain the reason
for it.
This time I use (m64_segsize >> 2) instead of (m64_segsize >> 1), since I
decide to still use ">" instead of ">=". By doing so, the explanation in
commit log is consistent with the code.
It should be:
const resource_size_t gate = phb->ioda.m64_segsize >> 1;
as it never changes in the function.
Good.
quoted
struct pci_dn *pdn;
int mul, total_vfs;
@@ -2704,6 +2704,17 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) total_vfs = pci_sriov_get_totalvfs(pdev); mul = phb->ioda.total_pe;+ /*+ * If bigger than or equal to half of M64 segment size, just round up+ * power of two.+ *+ * Generally, one M64 BAR maps one IOV BAR. To avoid conflict with+ * other devices, IOV BAR size is expanded to be (total_pe *+ * VF_BAR_size). When VF_BAR_size is half of M64 segment size , the+ * expanded size would equal to half of the whole M64 Space size,+ * which will exhaust the M64 Space and limit the system flexibility.+ */+ gate = phb->ioda.m64_segsize >> 1; for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { res = &pdev->resource[i + PCI_IOV_RESOURCES];
@@ -2718,10 +2729,11 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES);- /* bigger than 64M */- if (size > (1 << 26)) {- dev_info(&pdev->dev, "PowerNV: VF BAR%d: %pR IOV size is bigger than 64M, roundup power2\n",- i, res);+ /* bigger than or equal to gate */
That multiline comment is better to be here, I think.
As you wish.
quoted
+ if (size >= gate) {
+ dev_info(&pdev->dev, "PowerNV: VF BAR%d: %pR IOV size "
+ "is bigger than %lld, roundup power2\n",
+ i, res, gate);
mul = roundup_pow_of_two(total_vfs);
pdn->m64_single_mode = true;
break;