linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Set PCIE maxpayload for card during hotplug insertion
@ 2011-03-24 22:21 Jordan Hargrave
  2011-03-25  1:06 ` Kenji Kaneshige
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Jordan Hargrave @ 2011-03-24 22:21 UTC (permalink / raw)
  To: linux-hotplug

Reference: http://marc.info/?l=linux-hotplug&m\x128932324625063&w=2

The following patch sets the MaxPayload setting to match the parent reading when inserting
a PCIE card into a hotplug slot.  On our system, the upstream bridge is set to 256, but when
inserting a card, the card setting defaults to 128.  As soon as I/O is performed to the card
it starts receiving errors since the payload size is too small.

Signed-off-by: Jordan_Hargrave@dell.com

---
 drivers/pci/hotplug/pcihp_slot.c |   45 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c
index 80b461c..912d55b 100644
--- a/drivers/pci/hotplug/pcihp_slot.c
+++ b/drivers/pci/hotplug/pcihp_slot.c
@@ -158,6 +158,47 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
 	 */
 }
 
+/* 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;
@@ -169,6 +210,10 @@ void pci_configure_slot(struct pci_dev *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");
+
 	memset(&hpp, 0, sizeof(hpp));
 	ret = pci_get_hp_params(dev, &hpp);
 	if (ret)
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-05-10 22:13 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-24 22:21 [PATCH] Set PCIE maxpayload for card during hotplug insertion Jordan Hargrave
2011-03-25  1:06 ` Kenji Kaneshige
2011-03-28  7:52 ` Jordan_Hargrave
2011-03-29 21:42 ` Jordan_Hargrave
2011-04-12 16:08 ` Jesse Barnes
2011-05-04 18:42 ` Jordan_Hargrave
2011-05-09 19:18 ` Jesse Barnes
2011-05-10 22:13 ` Kenji Kaneshige

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).