Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-09-19 17:07:41 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2011-09-19 17:07:41 -0700
commit270f40afd1af8010222b61b4ac560c967d6fb0a4 (patch)
tree6c9468a6b3bff57ea37af6fbc62a9cd9b74d69e3
parentd126664e9e1e9e4b12abae466d121a1634471c89 (diff)
- More 3.0.5 patches:
- patches.kernel.org/fs-9p-add-os-dependent-open-flags-in-9p-protocol.patch: fs/9p: Add OS dependent open flags in 9p protocol. - patches.kernel.org/fs-9p-use-protocol-defined-value-for-lock-getlock-type-field.patch: Refresh. - patches.kernel.org/pci-export-pcie_bus_configure_settings-symbol.patch: PCI: export pcie_bus_configure_settings symbol. - patches.kernel.org/pci-remove-mrrs-modification-from-mps-setting-code.patch: PCI: Remove MRRS modification from MPS setting code. - patches.kernel.org/pci-set-pci-e-max-payload-size-on-fabric.patch: PCI: Set PCI-E Max Payload Size on fabric.
-rw-r--r--kernel-source.changes15
-rw-r--r--patches.kernel.org/fs-9p-add-os-dependent-open-flags-in-9p-protocol.patch169
-rw-r--r--patches.kernel.org/fs-9p-use-protocol-defined-value-for-lock-getlock-type-field.patch2
-rw-r--r--patches.kernel.org/pci-export-pcie_bus_configure_settings-symbol.patch31
-rw-r--r--patches.kernel.org/pci-remove-mrrs-modification-from-mps-setting-code.patch117
-rw-r--r--patches.kernel.org/pci-set-pci-e-max-payload-size-on-fabric.patch445
-rw-r--r--series.conf6
7 files changed, 782 insertions, 3 deletions
diff --git a/kernel-source.changes b/kernel-source.changes
index 0751695406..cf83f47c45 100644
--- a/kernel-source.changes
+++ b/kernel-source.changes
@@ -1,4 +1,19 @@
-------------------------------------------------------------------
+Tue Sep 20 02:07:29 CEST 2011 - gregkh@suse.de
+
+- More 3.0.5 patches:
+- patches.kernel.org/fs-9p-add-os-dependent-open-flags-in-9p-protocol.patch:
+ fs/9p: Add OS dependent open flags in 9p protocol.
+- patches.kernel.org/fs-9p-use-protocol-defined-value-for-lock-getlock-type-field.patch:
+ Refresh.
+- patches.kernel.org/pci-export-pcie_bus_configure_settings-symbol.patch:
+ PCI: export pcie_bus_configure_settings symbol.
+- patches.kernel.org/pci-remove-mrrs-modification-from-mps-setting-code.patch:
+ PCI: Remove MRRS modification from MPS setting code.
+- patches.kernel.org/pci-set-pci-e-max-payload-size-on-fabric.patch:
+ PCI: Set PCI-E Max Payload Size on fabric.
+
+-------------------------------------------------------------------
Mon Sep 19 23:16:13 CEST 2011 - jeffm@suse.com
- Update config files: Enabled PNFS support (FATE#310250).
diff --git a/patches.kernel.org/fs-9p-add-os-dependent-open-flags-in-9p-protocol.patch b/patches.kernel.org/fs-9p-add-os-dependent-open-flags-in-9p-protocol.patch
new file mode 100644
index 0000000000..bfc9d49a70
--- /dev/null
+++ b/patches.kernel.org/fs-9p-add-os-dependent-open-flags-in-9p-protocol.patch
@@ -0,0 +1,169 @@
+From f88657ce3f9713a0c62101dffb0e972a979e77b9 Mon Sep 17 00:00:00 2001
+From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
+Date: Wed, 3 Aug 2011 19:55:32 +0530
+Subject: fs/9p: Add OS dependent open flags in 9p protocol
+
+From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
+
+commit f88657ce3f9713a0c62101dffb0e972a979e77b9 upstream.
+
+Some of the flags are OS/arch dependent we add a 9p
+protocol value which maps to asm-generic/fcntl.h values in Linux
+Based on the original patch from Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
+
+[extra comments from author as to why this needs to go to stable:
+
+Earlier for different operation such as open we used the values of open
+flag as defined by the OS. But some of these flags such as O_DIRECT are
+arch dependent. So if we have the 9p client and server running on
+different architectures, we end up with client sending client
+architecture value of these open flag and server will try to map these
+values to what its architecture states. For ex: O_DIRECT on a x86 client
+maps to
+
+#define O_DIRECT 00040000
+
+Where as on sparc server it will maps to
+
+#define O_DIRECT 0x100000
+
+Hence we need to map these open flags to OS/arch independent flag
+values. Getting these changes to an early version of kernel ensures us
+that we work with different combination of client and server. We should
+ideally backport this patch to all possible kernel version.]
+
+Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/9p/v9fs_vfs.h | 2 +
+ fs/9p/vfs_file.c | 2 -
+ fs/9p/vfs_inode_dotl.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ include/net/9p/9p.h | 24 +++++++++++++++++++++
+ 4 files changed, 81 insertions(+), 2 deletions(-)
+
+--- a/fs/9p/v9fs_vfs.h
++++ b/fs/9p/v9fs_vfs.h
+@@ -82,4 +82,6 @@ static inline void v9fs_invalidate_inode
+ v9inode->cache_validity |= V9FS_INO_INVALID_ATTR;
+ return;
+ }
++
++int v9fs_open_to_dotl_flags(int flags);
+ #endif
+--- a/fs/9p/vfs_file.c
++++ b/fs/9p/vfs_file.c
+@@ -65,7 +65,7 @@ int v9fs_file_open(struct inode *inode,
+ v9inode = V9FS_I(inode);
+ v9ses = v9fs_inode2v9ses(inode);
+ if (v9fs_proto_dotl(v9ses))
+- omode = file->f_flags;
++ omode = v9fs_open_to_dotl_flags(file->f_flags);
+ else
+ omode = v9fs_uflags2omode(file->f_flags,
+ v9fs_proto_dotu(v9ses));
+--- a/fs/9p/vfs_inode_dotl.c
++++ b/fs/9p/vfs_inode_dotl.c
+@@ -191,6 +191,58 @@ v9fs_inode_from_fid_dotl(struct v9fs_ses
+ return inode;
+ }
+
++struct dotl_openflag_map {
++ int open_flag;
++ int dotl_flag;
++};
++
++static int v9fs_mapped_dotl_flags(int flags)
++{
++ int i;
++ int rflags = 0;
++ struct dotl_openflag_map dotl_oflag_map[] = {
++ { O_CREAT, P9_DOTL_CREATE },
++ { O_EXCL, P9_DOTL_EXCL },
++ { O_NOCTTY, P9_DOTL_NOCTTY },
++ { O_TRUNC, P9_DOTL_TRUNC },
++ { O_APPEND, P9_DOTL_APPEND },
++ { O_NONBLOCK, P9_DOTL_NONBLOCK },
++ { O_DSYNC, P9_DOTL_DSYNC },
++ { FASYNC, P9_DOTL_FASYNC },
++ { O_DIRECT, P9_DOTL_DIRECT },
++ { O_LARGEFILE, P9_DOTL_LARGEFILE },
++ { O_DIRECTORY, P9_DOTL_DIRECTORY },
++ { O_NOFOLLOW, P9_DOTL_NOFOLLOW },
++ { O_NOATIME, P9_DOTL_NOATIME },
++ { O_CLOEXEC, P9_DOTL_CLOEXEC },
++ { O_SYNC, P9_DOTL_SYNC},
++ };
++ for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) {
++ if (flags & dotl_oflag_map[i].open_flag)
++ rflags |= dotl_oflag_map[i].dotl_flag;
++ }
++ return rflags;
++}
++
++/**
++ * v9fs_open_to_dotl_flags- convert Linux specific open flags to
++ * plan 9 open flag.
++ * @flags: flags to convert
++ */
++int v9fs_open_to_dotl_flags(int flags)
++{
++ int rflags = 0;
++
++ /*
++ * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY
++ * and P9_DOTL_NOACCESS
++ */
++ rflags |= flags & O_ACCMODE;
++ rflags |= v9fs_mapped_dotl_flags(flags);
++
++ return rflags;
++}
++
+ /**
+ * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol.
+ * @dir: directory inode that is being created
+@@ -259,7 +311,8 @@ v9fs_vfs_create_dotl(struct inode *dir,
+ "Failed to get acl values in creat %d\n", err);
+ goto error;
+ }
+- err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid);
++ err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
++ mode, gid, &qid);
+ if (err < 0) {
+ P9_DPRINTK(P9_DEBUG_VFS,
+ "p9_client_open_dotl failed in creat %d\n",
+--- a/include/net/9p/9p.h
++++ b/include/net/9p/9p.h
+@@ -278,6 +278,30 @@ enum p9_perm_t {
+ P9_DMSETVTX = 0x00010000,
+ };
+
++/* 9p2000.L open flags */
++#define P9_DOTL_RDONLY 00000000
++#define P9_DOTL_WRONLY 00000001
++#define P9_DOTL_RDWR 00000002
++#define P9_DOTL_NOACCESS 00000003
++#define P9_DOTL_CREATE 00000100
++#define P9_DOTL_EXCL 00000200
++#define P9_DOTL_NOCTTY 00000400
++#define P9_DOTL_TRUNC 00001000
++#define P9_DOTL_APPEND 00002000
++#define P9_DOTL_NONBLOCK 00004000
++#define P9_DOTL_DSYNC 00010000
++#define P9_DOTL_FASYNC 00020000
++#define P9_DOTL_DIRECT 00040000
++#define P9_DOTL_LARGEFILE 00100000
++#define P9_DOTL_DIRECTORY 00200000
++#define P9_DOTL_NOFOLLOW 00400000
++#define P9_DOTL_NOATIME 01000000
++#define P9_DOTL_CLOEXEC 02000000
++#define P9_DOTL_SYNC 04000000
++
++/* 9p2000.L at flags */
++#define P9_DOTL_AT_REMOVEDIR 0x200
++
+ /**
+ * enum p9_qid_t - QID types
+ * @P9_QTDIR: directory
diff --git a/patches.kernel.org/fs-9p-use-protocol-defined-value-for-lock-getlock-type-field.patch b/patches.kernel.org/fs-9p-use-protocol-defined-value-for-lock-getlock-type-field.patch
index 65f4ed10d6..a4f449b046 100644
--- a/patches.kernel.org/fs-9p-use-protocol-defined-value-for-lock-getlock-type-field.patch
+++ b/patches.kernel.org/fs-9p-use-protocol-defined-value-for-lock-getlock-type-field.patch
@@ -82,7 +82,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
-@@ -320,6 +320,11 @@ enum p9_qid_t {
+@@ -344,6 +344,11 @@ enum p9_qid_t {
/* Room for readdir header */
#define P9_READDIRHDRSZ 24
diff --git a/patches.kernel.org/pci-export-pcie_bus_configure_settings-symbol.patch b/patches.kernel.org/pci-export-pcie_bus_configure_settings-symbol.patch
new file mode 100644
index 0000000000..1812baf6d8
--- /dev/null
+++ b/patches.kernel.org/pci-export-pcie_bus_configure_settings-symbol.patch
@@ -0,0 +1,31 @@
+From debc3b778508f59696ff188f0feca271dcbfa7d9 Mon Sep 17 00:00:00 2001
+From: Jon Mason <mason@myri.com>
+Date: Tue, 2 Aug 2011 00:01:18 -0500
+Subject: PCI: export pcie_bus_configure_settings symbol
+
+From: Jon Mason <mason@myri.com>
+
+commit debc3b778508f59696ff188f0feca271dcbfa7d9 upstream.
+
+pcie_bus_configure_settings needs to be exported if the PCI hotplug
+driver is being compiled as a module.
+
+Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Signed-off-by: Jon Mason <mason@myri.com>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/probe.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -1471,6 +1471,7 @@ void pcie_bus_configure_settings(struct
+ pcie_bus_configure_set(bus->self, &smpss);
+ pci_walk_bus(bus, pcie_bus_configure_set, &smpss);
+ }
++EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
+
+ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+ {
diff --git a/patches.kernel.org/pci-remove-mrrs-modification-from-mps-setting-code.patch b/patches.kernel.org/pci-remove-mrrs-modification-from-mps-setting-code.patch
new file mode 100644
index 0000000000..7c0f5cd028
--- /dev/null
+++ b/patches.kernel.org/pci-remove-mrrs-modification-from-mps-setting-code.patch
@@ -0,0 +1,117 @@
+From ed2888e906b56769b4ffabb9c577190438aa68b8 Mon Sep 17 00:00:00 2001
+From: Jon Mason <mason@myri.com>
+Date: Thu, 8 Sep 2011 16:41:18 -0500
+Subject: PCI: Remove MRRS modification from MPS setting code
+
+From: Jon Mason <mason@myri.com>
+
+commit ed2888e906b56769b4ffabb9c577190438aa68b8 upstream.
+
+Modifying the Maximum Read Request Size to 0 (value of 128Bytes) has
+massive negative ramifications on some devices. Without knowing which
+devices have this issue, do not modify from the default value when
+walking the PCI-E bus in pcie_bus_safe mode. Also, make pcie_bus_safe
+the default procedure.
+
+Tested-by: Sven Schnelle <svens@stackframe.org>
+Tested-by: Simon Kirby <sim@hostway.ca>
+Tested-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
+Reported-and-tested-by: Eric Dumazet <eric.dumazet@gmail.com>
+Reported-and-tested-by: Niels Ole Salscheider <niels_ole@salscheider-online.de>
+References: https://bugzilla.kernel.org/show_bug.cgi?id=42162
+Signed-off-by: Jon Mason <mason@myri.com>
+Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/pci.c | 2 +-
+ drivers/pci/probe.c | 45 ++++++++++++++++++++++++---------------------
+ 2 files changed, 25 insertions(+), 22 deletions(-)
+
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -77,7 +77,7 @@ unsigned long pci_cardbus_mem_size = DEF
+ unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE;
+ unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
+
+-enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PERFORMANCE;
++enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_SAFE;
+
+ /*
+ * The default CLS is used if arch didn't set CLS explicitly and not
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -1397,34 +1397,37 @@ static void pcie_write_mps(struct pci_de
+
+ static void pcie_write_mrrs(struct pci_dev *dev, int mps)
+ {
+- int rc, mrrs;
+-
+- if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
+- int dev_mpss = 128 << dev->pcie_mpss;
+-
+- /* For Max performance, the MRRS must be set to the largest
+- * supported value. However, it cannot be configured larger
+- * than the MPS the device or the bus can support. This assumes
+- * that the largest MRRS available on the device cannot be
+- * smaller than the device MPSS.
+- */
+- mrrs = mps < dev_mpss ? mps : dev_mpss;
+- } else
+- /* In the "safe" case, configure the MRRS for fairness on the
+- * bus by making all devices have the same size
+- */
+- mrrs = mps;
++ int rc, mrrs, dev_mpss;
+
++ /* In the "safe" case, do not configure the MRRS. There appear to be
++ * issues with setting MRRS to 0 on a number of devices.
++ */
++
++ if (pcie_bus_config != PCIE_BUS_PERFORMANCE)
++ return;
++
++ dev_mpss = 128 << dev->pcie_mpss;
++
++ /* For Max performance, the MRRS must be set to the largest supported
++ * value. However, it cannot be configured larger than the MPS the
++ * device or the bus can support. This assumes that the largest MRRS
++ * available on the device cannot be smaller than the device MPSS.
++ */
++ mrrs = min(mps, dev_mpss);
+
+ /* MRRS is a R/W register. Invalid values can be written, but a
+- * subsiquent read will verify if the value is acceptable or not.
++ * subsequent read will verify if the value is acceptable or not.
+ * If the MRRS value provided is not acceptable (e.g., too large),
+ * shrink the value until it is acceptable to the HW.
+ */
+ while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) {
++ dev_warn(&dev->dev, "Attempting to modify the PCI-E MRRS value"
++ " to %d. If any issues are encountered, please try "
++ "running with pci=pcie_bus_safe\n", mrrs);
+ rc = pcie_set_readrq(dev, mrrs);
+ if (rc)
+- dev_err(&dev->dev, "Failed attempting to set the MRRS\n");
++ dev_err(&dev->dev,
++ "Failed attempting to set the MRRS\n");
+
+ mrrs /= 2;
+ }
+@@ -1437,13 +1440,13 @@ static int pcie_bus_configure_set(struct
+ if (!pci_is_pcie(dev))
+ return 0;
+
+- dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
++ dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
+ pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
+
+ pcie_write_mps(dev, mps);
+ pcie_write_mrrs(dev, mps);
+
+- dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
++ dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
+ pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
+
+ return 0;
diff --git a/patches.kernel.org/pci-set-pci-e-max-payload-size-on-fabric.patch b/patches.kernel.org/pci-set-pci-e-max-payload-size-on-fabric.patch
new file mode 100644
index 0000000000..6ca45f3804
--- /dev/null
+++ b/patches.kernel.org/pci-set-pci-e-max-payload-size-on-fabric.patch
@@ -0,0 +1,445 @@
+From b03e7495a862b028294f59fc87286d6d78ee7fa1 Mon Sep 17 00:00:00 2001
+From: Jon Mason <mason@myri.com>
+Date: Wed, 20 Jul 2011 15:20:54 -0500
+Subject: PCI: Set PCI-E Max Payload Size on fabric
+
+From: Jon Mason <mason@myri.com>
+
+commit b03e7495a862b028294f59fc87286d6d78ee7fa1 upstream.
+
+On a given PCI-E fabric, each device, bridge, and root port can have a
+different PCI-E maximum payload size. There is a sizable performance
+boost for having the largest possible maximum payload size on each PCI-E
+device. However, if improperly configured, fatal bus errors can occur.
+Thus, it is important to ensure that PCI-E payloads sends by a device
+are never larger than the MPS setting of all devices on the way to the
+destination.
+
+This can be achieved two ways:
+
+- A conservative approach is to use the smallest common denominator of
+ the entire tree below a root complex for every device on that fabric.
+
+This means for example that having a 128 bytes MPS USB controller on one
+leg of a switch will dramatically reduce performances of a video card or
+10GE adapter on another leg of that same switch.
+
+It also means that any hierarchy supporting hotplug slots (including
+expresscard or thunderbolt I suppose, dbl check that) will have to be
+entirely clamped to 128 bytes since we cannot predict what will be
+plugged into those slots, and we cannot change the MPS on a "live"
+system.
+
+- A more optimal way is possible, if it falls within a couple of
+ constraints:
+* The top-level host bridge will never generate packets larger than the
+ smallest TLP (or if it can be controlled independently from its MPS at
+ least)
+* The device will never generate packets larger than MPS (which can be
+ configured via MRRS)
+* No support of direct PCI-E <-> PCI-E transfers between devices without
+ some additional code to specifically deal with that case
+
+Then we can use an approach that basically ignores downstream requests
+and focuses exclusively on upstream requests. In that case, all we need
+to care about is that a device MPS is no larger than its parent MPS,
+which allows us to keep all switches/bridges to the max MPS supported by
+their parent and eventually the PHB.
+
+In this case, your USB controller would no longer "starve" your 10GE
+Ethernet and your hotplug slots won't affect your global MPS.
+Additionally, the hotplugged devices themselves can be configured to a
+larger MPS up to the value configured in the hotplug bridge.
+
+To choose between the two available options, two PCI kernel boot args
+have been added to the PCI calls. "pcie_bus_safe" will provide the
+former behavior, while "pcie_bus_perf" will perform the latter behavior.
+By default, the latter behavior is used.
+
+NOTE: due to the location of the enablement, each arch will need to add
+calls to this function. This patch only enables x86.
+
+This patch includes a number of changes recommended by Benjamin
+Herrenschmidt.
+
+Tested-by: Jordan_Hargrave@dell.com
+Signed-off-by: Jon Mason <mason@myri.com>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/pci/acpi.c | 9 ++
+ drivers/pci/hotplug/pcihp_slot.c | 45 ------------
+ drivers/pci/pci.c | 67 ++++++++++++++++++
+ drivers/pci/probe.c | 145 +++++++++++++++++++++++++++++++++++++++
+ include/linux/pci.h | 15 +++-
+ 5 files changed, 236 insertions(+), 45 deletions(-)
+
+--- a/arch/x86/pci/acpi.c
++++ b/arch/x86/pci/acpi.c
+@@ -361,6 +361,15 @@ struct pci_bus * __devinit pci_acpi_scan
+ }
+ }
+
++ /* After the PCI-E bus has been walked and all devices discovered,
++ * configure any settings of the fabric that might be necessary.
++ */
++ if (bus) {
++ struct pci_bus *child;
++ list_for_each_entry(child, &bus->children, node)
++ pcie_bus_configure_settings(child, child->self->pcie_mpss);
++ }
++
+ if (!bus)
+ kfree(sd);
+
+--- a/drivers/pci/hotplug/pcihp_slot.c
++++ b/drivers/pci/hotplug/pcihp_slot.c
+@@ -158,47 +158,6 @@ static void program_hpp_type2(struct pci
+ */
+ }
+
+-/* Program PCIE MaxPayload setting on device: ensure parent maxpayload <= device */
+-static int pci_set_payload(struct pci_dev *dev)
+-{
+- int pos, ppos;
+- u16 pctl, psz;
+- u16 dctl, dsz, dcap, dmax;
+- struct pci_dev *parent;
+-
+- parent = dev->bus->self;
+- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+- if (!pos)
+- return 0;
+-
+- /* Read Device MaxPayload capability and setting */
+- pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &dctl);
+- pci_read_config_word(dev, pos + PCI_EXP_DEVCAP, &dcap);
+- dsz = (dctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
+- dmax = (dcap & PCI_EXP_DEVCAP_PAYLOAD);
+-
+- /* Read Parent MaxPayload setting */
+- ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+- if (!ppos)
+- return 0;
+- pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
+- psz = (pctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
+-
+- /* If parent payload > device max payload -> error
+- * If parent payload > device payload -> set speed
+- * If parent payload <= device payload -> do nothing
+- */
+- if (psz > dmax)
+- return -1;
+- else if (psz > dsz) {
+- dev_info(&dev->dev, "Setting MaxPayload to %d\n", 128 << psz);
+- pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
+- (dctl & ~PCI_EXP_DEVCTL_PAYLOAD) +
+- (psz << 5));
+- }
+- return 0;
+-}
+-
+ void pci_configure_slot(struct pci_dev *dev)
+ {
+ struct pci_dev *cdev;
+@@ -210,9 +169,7 @@ void pci_configure_slot(struct pci_dev *
+ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+ return;
+
+- ret = pci_set_payload(dev);
+- if (ret)
+- dev_warn(&dev->dev, "could not set device max payload\n");
++ pcie_bus_configure_settings(dev->bus, dev->bus->self->pcie_mpss);
+
+ memset(&hpp, 0, sizeof(hpp));
+ ret = pci_get_hp_params(dev, &hpp);
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -77,6 +77,8 @@ unsigned long pci_cardbus_mem_size = DEF
+ unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE;
+ unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
+
++enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PERFORMANCE;
++
+ /*
+ * The default CLS is used if arch didn't set CLS explicitly and not
+ * all pci devices agree on the same value. Arch can override either
+@@ -3223,6 +3225,67 @@ out:
+ EXPORT_SYMBOL(pcie_set_readrq);
+
+ /**
++ * pcie_get_mps - get PCI Express maximum payload size
++ * @dev: PCI device to query
++ *
++ * Returns maximum payload size in bytes
++ * or appropriate error value.
++ */
++int pcie_get_mps(struct pci_dev *dev)
++{
++ int ret, cap;
++ u16 ctl;
++
++ cap = pci_pcie_cap(dev);
++ if (!cap)
++ return -EINVAL;
++
++ ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
++ if (!ret)
++ ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
++
++ return ret;
++}
++
++/**
++ * pcie_set_mps - set PCI Express maximum payload size
++ * @dev: PCI device to query
++ * @rq: maximum payload size in bytes
++ * valid values are 128, 256, 512, 1024, 2048, 4096
++ *
++ * If possible sets maximum payload size
++ */
++int pcie_set_mps(struct pci_dev *dev, int mps)
++{
++ int cap, err = -EINVAL;
++ u16 ctl, v;
++
++ if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
++ goto out;
++
++ v = ffs(mps) - 8;
++ if (v > dev->pcie_mpss)
++ goto out;
++ v <<= 5;
++
++ cap = pci_pcie_cap(dev);
++ if (!cap)
++ goto out;
++
++ err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
++ if (err)
++ goto out;
++
++ if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) {
++ ctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
++ ctl |= v;
++ err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
++ }
++out:
++ return err;
++}
++
++/**
+ * pci_select_bars - Make BAR mask from the type of resource
+ * @dev: the PCI device for which BAR mask is made
+ * @flags: resource type mask to be selected
+@@ -3505,6 +3568,10 @@ static int __init pci_setup(char *str)
+ pci_hotplug_io_size = memparse(str + 9, &str);
+ } else if (!strncmp(str, "hpmemsize=", 10)) {
+ pci_hotplug_mem_size = memparse(str + 10, &str);
++ } else if (!strncmp(str, "pcie_bus_safe", 13)) {
++ pcie_bus_config = PCIE_BUS_SAFE;
++ } else if (!strncmp(str, "pcie_bus_perf", 13)) {
++ pcie_bus_config = PCIE_BUS_PERFORMANCE;
+ } else {
+ printk(KERN_ERR "PCI: Unknown option `%s'\n",
+ str);
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -860,6 +860,8 @@ void set_pcie_port_type(struct pci_dev *
+ pdev->pcie_cap = pos;
+ pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
+ pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4;
++ pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16);
++ pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
+ }
+
+ void set_pcie_hotplug_bridge(struct pci_dev *pdev)
+@@ -1327,6 +1329,149 @@ int pci_scan_slot(struct pci_bus *bus, i
+ return nr;
+ }
+
++static int pcie_find_smpss(struct pci_dev *dev, void *data)
++{
++ u8 *smpss = data;
++
++ if (!pci_is_pcie(dev))
++ return 0;
++
++ /* For PCIE hotplug enabled slots not connected directly to a
++ * PCI-E root port, there can be problems when hotplugging
++ * devices. This is due to the possibility of hotplugging a
++ * device into the fabric with a smaller MPS that the devices
++ * currently running have configured. Modifying the MPS on the
++ * running devices could cause a fatal bus error due to an
++ * incoming frame being larger than the newly configured MPS.
++ * To work around this, the MPS for the entire fabric must be
++ * set to the minimum size. Any devices hotplugged into this
++ * fabric will have the minimum MPS set. If the PCI hotplug
++ * slot is directly connected to the root port and there are not
++ * other devices on the fabric (which seems to be the most
++ * common case), then this is not an issue and MPS discovery
++ * will occur as normal.
++ */
++ if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) ||
++ dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT))
++ *smpss = 0;
++
++ if (*smpss > dev->pcie_mpss)
++ *smpss = dev->pcie_mpss;
++
++ return 0;
++}
++
++static void pcie_write_mps(struct pci_dev *dev, int mps)
++{
++ int rc, dev_mpss;
++
++ dev_mpss = 128 << dev->pcie_mpss;
++
++ if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
++ if (dev->bus->self) {
++ dev_dbg(&dev->bus->dev, "Bus MPSS %d\n",
++ 128 << dev->bus->self->pcie_mpss);
++
++ /* For "MPS Force Max", the assumption is made that
++ * downstream communication will never be larger than
++ * the MRRS. So, the MPS only needs to be configured
++ * for the upstream communication. This being the case,
++ * walk from the top down and set the MPS of the child
++ * to that of the parent bus.
++ */
++ mps = 128 << dev->bus->self->pcie_mpss;
++ if (mps > dev_mpss)
++ dev_warn(&dev->dev, "MPS configured higher than"
++ " maximum supported by the device. If"
++ " a bus issue occurs, try running with"
++ " pci=pcie_bus_safe.\n");
++ }
++
++ dev->pcie_mpss = ffs(mps) - 8;
++ }
++
++ rc = pcie_set_mps(dev, mps);
++ if (rc)
++ dev_err(&dev->dev, "Failed attempting to set the MPS\n");
++}
++
++static void pcie_write_mrrs(struct pci_dev *dev, int mps)
++{
++ int rc, mrrs;
++
++ if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
++ int dev_mpss = 128 << dev->pcie_mpss;
++
++ /* For Max performance, the MRRS must be set to the largest
++ * supported value. However, it cannot be configured larger
++ * than the MPS the device or the bus can support. This assumes
++ * that the largest MRRS available on the device cannot be
++ * smaller than the device MPSS.
++ */
++ mrrs = mps < dev_mpss ? mps : dev_mpss;
++ } else
++ /* In the "safe" case, configure the MRRS for fairness on the
++ * bus by making all devices have the same size
++ */
++ mrrs = mps;
++
++
++ /* MRRS is a R/W register. Invalid values can be written, but a
++ * subsiquent read will verify if the value is acceptable or not.
++ * If the MRRS value provided is not acceptable (e.g., too large),
++ * shrink the value until it is acceptable to the HW.
++ */
++ while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) {
++ rc = pcie_set_readrq(dev, mrrs);
++ if (rc)
++ dev_err(&dev->dev, "Failed attempting to set the MRRS\n");
++
++ mrrs /= 2;
++ }
++}
++
++static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
++{
++ int mps = 128 << *(u8 *)data;
++
++ if (!pci_is_pcie(dev))
++ return 0;
++
++ dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
++ pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
++
++ pcie_write_mps(dev, mps);
++ pcie_write_mrrs(dev, mps);
++
++ dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
++ pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
++
++ return 0;
++}
++
++/* pcie_bus_configure_mps requires that pci_walk_bus work in a top-down,
++ * parents then children fashion. If this changes, then this code will not
++ * work as designed.
++ */
++void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
++{
++ u8 smpss = mpss;
++
++ if (!bus->self)
++ return;
++
++ if (!pci_is_pcie(bus->self))
++ return;
++
++ if (pcie_bus_config == PCIE_BUS_SAFE) {
++ pcie_find_smpss(bus->self, &smpss);
++ pci_walk_bus(bus, pcie_find_smpss, &smpss);
++ }
++
++ pcie_bus_configure_set(bus->self, &smpss);
++ pci_walk_bus(bus, pcie_bus_configure_set, &smpss);
++}
++
+ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+ {
+ unsigned int devfn, pass, max = bus->secondary;
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -251,7 +251,8 @@ struct pci_dev {
+ u8 revision; /* PCI revision, low byte of class word */
+ u8 hdr_type; /* PCI header type (`multi' flag masked out) */
+ u8 pcie_cap; /* PCI-E capability offset */
+- u8 pcie_type; /* PCI-E device/port type */
++ u8 pcie_type:4; /* PCI-E device/port type */
++ u8 pcie_mpss:3; /* PCI-E Max Payload Size Supported */
+ u8 rom_base_reg; /* which config register controls the ROM */
+ u8 pin; /* which interrupt pin this device uses */
+
+@@ -617,6 +618,16 @@ struct pci_driver {
+ /* these external functions are only available when PCI support is enabled */
+ #ifdef CONFIG_PCI
+
++extern void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss);
++
++enum pcie_bus_config_types {
++ PCIE_BUS_PERFORMANCE,
++ PCIE_BUS_SAFE,
++ PCIE_BUS_PEER2PEER,
++};
++
++extern enum pcie_bus_config_types pcie_bus_config;
++
+ extern struct bus_type pci_bus_type;
+
+ /* Do NOT directly access these two variables, unless you are arch specific pci
+@@ -796,6 +807,8 @@ int pcix_get_mmrbc(struct pci_dev *dev);
+ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
+ int pcie_get_readrq(struct pci_dev *dev);
+ int pcie_set_readrq(struct pci_dev *dev, int rq);
++int pcie_get_mps(struct pci_dev *dev);
++int pcie_set_mps(struct pci_dev *dev, int mps);
+ int __pci_reset_function(struct pci_dev *dev);
+ int pci_reset_function(struct pci_dev *dev);
+ void pci_update_resource(struct pci_dev *dev, int resno);
diff --git a/series.conf b/series.conf
index da3486efd4..374b177bd0 100644
--- a/series.conf
+++ b/series.conf
@@ -127,9 +127,13 @@
patches.kernel.org/acpica-do-not-repair-_tss-return-package-if-_pss-is-present.patch
patches.kernel.org/fs-9p-add-fid-before-dentry-instantiation.patch
patches.kernel.org/fs-9p-don-t-update-file-type-when-updating-file-attributes.patch
+ patches.kernel.org/fs-9p-add-os-dependent-open-flags-in-9p-protocol.patch
patches.kernel.org/net-9p-fix-kernel-crash-with-msize-512k.patch
patches.kernel.org/fs-9p-always-ask-new-inode-in-lookup-for-cache-mode.patch
patches.kernel.org/fs-9p-use-protocol-defined-value-for-lock-getlock-type-field.patch
+ patches.kernel.org/pci-set-pci-e-max-payload-size-on-fabric.patch
+ patches.kernel.org/pci-export-pcie_bus_configure_settings-symbol.patch
+ patches.kernel.org/pci-remove-mrrs-modification-from-mps-setting-code.patch
########################################################
# Build fixes that apply to the vanilla kernel too.
@@ -1243,8 +1247,6 @@
########################################################
patches.fixes/pci_use_acpi_resources_whitelist.patch
patches.arch/x86_PCI-Preserve-existing-pci_bfsort-whitelist-for-Dell-systems.patch
- patches.drivers/pci-set-pci-e-max-payload-size-on-fabric.patch
- patches.drivers/pci-export-pcie_bus_configure_settings-symbol.patch
########################################################
# sysfs / driver core