summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2016-06-15 14:07:51 +0300
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-12-14 18:33:41 +0300
commit0b7589ecca2b6f962cf3314a3a5a675deeefb624 (patch)
tree0e76f58c9d6f5ae9cd9d172d3d6f9f11e29f8ba4
parentd03502684b65492339d70f11aa8ed6df3961a3bf (diff)
downloadlinux-0b7589ecca2b6f962cf3314a3a5a675deeefb624.tar.xz
s390/pci: query fmb length
Query the length of the fmb and abort fmb registration if the size of the associated measurement block is too small. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/pci.h1
-rw-r--r--arch/s390/include/asm/pci_clp.h3
-rw-r--r--arch/s390/pci/pci.c2
-rw-r--r--arch/s390/pci/pci_clp.c1
4 files changed, 5 insertions, 2 deletions
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 6611f798d2be..4e3186649578 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -133,6 +133,7 @@ struct zpci_dev {
/* Function measurement block */
struct zpci_fmb *fmb;
u16 fmb_update; /* update interval */
+ u16 fmb_length;
/* software counters */
atomic64_t allocated_pages;
atomic64_t mapped_pages;
diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h
index c232ef9711f5..d6f1b1d94352 100644
--- a/arch/s390/include/asm/pci_clp.h
+++ b/arch/s390/include/asm/pci_clp.h
@@ -87,7 +87,8 @@ struct clp_rsp_query_pci {
u16 pchid;
u32 bar[PCI_BAR_COUNT];
u8 pfip[CLP_PFIP_NR_SEGMENTS]; /* pci function internal path */
- u32 : 24;
+ u32 : 16;
+ u8 fmb_len;
u8 pft; /* pci function type */
u64 sdma; /* start dma as */
u64 edma; /* end dma as */
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 64e1734bebb7..38e17d4d9884 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -180,7 +180,7 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
{
struct mod_pci_args args = { 0, 0, 0, 0 };
- if (zdev->fmb)
+ if (zdev->fmb || sizeof(*zdev->fmb) < zdev->fmb_length)
return -EINVAL;
zdev->fmb = kmem_cache_zalloc(zdev_fmb_cache, GFP_KERNEL);
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c
index e3ef63b36b5a..1c3332ac1957 100644
--- a/arch/s390/pci/pci_clp.c
+++ b/arch/s390/pci/pci_clp.c
@@ -148,6 +148,7 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev,
zdev->pft = response->pft;
zdev->vfn = response->vfn;
zdev->uid = response->uid;
+ zdev->fmb_length = sizeof(u32) * response->fmb_len;
memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip));
if (response->util_str_avail) {