Skip to contentSkip to conversation

Reset PCIe devices to address DMA problem on kdump with iommu

RFC PATCH Superseded Takao Indoh 5 participants 21 messages Aug 3, 2012 – Sep 24, 2012

Subsystems (4)

v1 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 Reset PCIe devices to address DMA problem on kdump with iommu

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Background:
A kdump problem about DMA has been discussed for a long time. That is, when a kernel is switched to the kdump kernel DMA derived from first kernel affects second kernel. Recently this problem surfaces when iommu is used for PCI passthrough on KVM guest. In the case of the machine I use, when intel_iommu=on is specified, DMAR error is detected in kdump kernel and PCI SERR is also detected. Finally kdump fails because some devices does not work correctly.

The root cause is that ongoing DMA from first kernel causes DMAR fault because page table of DMAR is initialized while kdump kernel is booting up. Therefore to address this problem DMA needs to be stopped before DMAR is initialized at kdump kernel boot time. By this patch, PCIe devices are reset by hot reset and its DMA is stopped when reset_pcie_devices is specified. One problem of this solution is that VGA is reset and the monitor blacks out when the link between the port and VGA controller was reset. So this patch does not reset the port whose child endpoint is VGA device.

Any comments would be appreciated.

---
 Documentation/kernel-parameters.txt |    4 +
 drivers/pci/quirks.c                |   59 ++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)
Documentation/kernel-parameters.txt +4 -0
index e714a02..e694e9f 100644
@@ -2489,6 +2489,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	reset_devices	[KNL] Force drivers to reset the underlying device
 			during initialization.
 
+	reset_pcie_devices
+			[PCIE] Reset PCIe endpoint at boot time by sending a
+			hot reset to root port and downstream port
+
 	resume=		[SWSUSP]
 			Specify the partition device for software suspend
 			Format:
drivers/pci/quirks.c +59 -0

65 lines not on this page · raw message

#1 lore raw
Quoted 6 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

Thanks
Vivek

Quoted 103 lines

Background:
A kdump problem about DMA has been discussed for a long time. That is, when a kernel is switched to the kdump kernel DMA derived from first kernel affects second kernel. Recently this problem surfaces when iommu is used for PCI passthrough on KVM guest. In the case of the machine I use, when intel_iommu=on is specified, DMAR error is detected in kdump kernel and PCI SERR is also detected. Finally kdump fails because some devices does not work correctly.

The root cause is that ongoing DMA from first kernel causes DMAR fault because page table of DMAR is initialized while kdump kernel is booting up. Therefore to address this problem DMA needs to be stopped before DMAR is initialized at kdump kernel boot time. By this patch, PCIe devices are reset by hot reset and its DMA is stopped when reset_pcie_devices is specified. One problem of this solution is that VGA is reset and the monitor blacks out when the link between the port and VGA controller was reset. So this patch does not reset the port whose child endpoint is VGA device.

Any comments would be appreciated.

---
 Documentation/kernel-parameters.txt |    4 +
 drivers/pci/quirks.c                |   59 ++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)
Documentation/kernel-parameters.txt +4 -0
index e714a02..e694e9f 100644
@@ -2489,6 +2489,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	reset_devices	[KNL] Force drivers to reset the underlying device
 			during initialization.
 
+	reset_pcie_devices
+			[PCIE] Reset PCIe endpoint at boot time by sending a
+			hot reset to root port and downstream port
+
 	resume=		[SWSUSP]
 			Specify the partition device for software suspend
 			Format:
drivers/pci/quirks.c +52 -0
index 5155317..7f7fc02 100644
@@ -32,6 +32,65 @@
 #include "pci.h"
 
 /*
+ * Reset PCIe endpoint by sending a hot reset to root port and downstream port
+ */
+unsigned int reset_pcie_devices;
+EXPORT_SYMBOL(reset_pcie_devices);
+static int __init set_reset_pcie_devices(char *str)
+{
+	reset_pcie_devices = 1;
+	return 1;
+}
+__setup("reset_pcie_devices", set_reset_pcie_devices);
+
+static void __devinit quirk_pcie_device_reset(struct pci_dev *dev)
+{
+	struct pci_bus *subordinate;
+	struct pci_dev *child;
+	u16 ctrl;
+
+	if (!reset_pcie_devices || !pci_is_pcie(dev) || !dev->subordinate ||
+	    ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
+	     (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
+		return;
+
+	subordinate = dev->subordinate;
+	list_for_each_entry(child, &subordinate->devices, bus_list) {
+		if ((child->pcie_type == PCI_EXP_TYPE_UPSTREAM) ||
+		    (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) ||
+		    ((child->class >> 16) == PCI_BASE_CLASS_DISPLAY))
+		/* Don't reset switch, bridge, VGA device */
+		return;
+	}
+
+	dev_info(&dev->dev, "Reset Secondary bus\n");
+
+	list_for_each_entry(child, &subordinate->devices, bus_list) {
+		dev_info(&child->dev, "save state\n");
+		pci_save_state(child);
+	}
+
+	/* Assert Secondary Bus Reset */
+	pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl);
+	ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+
+	msleep(2);
+
+	/* De-assert Secondary Bus Reset */
+	ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+
+	msleep(200);
+
+	list_for_each_entry(child, &subordinate->devices, bus_list) {

drivers/pci/quirks.c line 96

Quoted 10 lines
drivers/pci/quirks.c +7 -0
+		dev_info(&child->dev, "restore state\n");
+		pci_restore_state(child);
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_pcie_device_reset);
+
+/*
  * Decoding should be disabled for a PCI device during BAR sizing to avoid
  * conflict. But doing so may cause problems on host bridge and perhaps other
  * key system devices. For devices that need to have mmio decoding always-on,

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#2 lore raw

Hi Vivek,

Quoted 8 lines · Vivek Goyal
Quoted 6 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Quoted 4 lines

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

"reset_devices" is used for each driver to reset their own device, and this patch resets all devices forcibly, so I thought they were different things.

Thanks,
Takao Indoh

Quoted 119 lines

Thanks
Vivek

Quoted 113 lines

Background:
A kdump problem about DMA has been discussed for a long time. That is, when a kernel is switched to the kdump kernel DMA derived from first kernel affects second kernel. Recently this problem surfaces when iommu is used for PCI passthrough on KVM guest. In the case of the machine I use, when intel_iommu=on is specified, DMAR error is detected in kdump kernel and PCI SERR is also detected. Finally kdump fails because some devices does not work correctly.

The root cause is that ongoing DMA from first kernel causes DMAR fault because page table of DMAR is initialized while kdump kernel is booting up. Therefore to address this problem DMA needs to be stopped before DMAR is initialized at kdump kernel boot time. By this patch, PCIe devices are reset by hot reset and its DMA is stopped when reset_pcie_devices is specified. One problem of this solution is that VGA is reset and the monitor blacks out when the link between the port and VGA controller was reset. So this patch does not reset the port whose child endpoint is VGA device.

Any comments would be appreciated.

---
  Documentation/kernel-parameters.txt |    4 +
  drivers/pci/quirks.c                |   59 ++++++++++++++++++++++++++
  2 files changed, 63 insertions(+)
Documentation/kernel-parameters.txt +4 -0
index e714a02..e694e9f 100644
@@ -2489,6 +2489,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
  	reset_devices	[KNL] Force drivers to reset the underlying device
  			during initialization.
 
+	reset_pcie_devices
+			[PCIE] Reset PCIe endpoint at boot time by sending a
+			hot reset to root port and downstream port
+
  	resume=		[SWSUSP]
  			Specify the partition device for software suspend
  			Format:
drivers/pci/quirks.c +59 -0
index 5155317..7f7fc02 100644
@@ -32,6 +32,65 @@
  #include "pci.h"
 
  /*
+ * Reset PCIe endpoint by sending a hot reset to root port and downstream port
+ */
+unsigned int reset_pcie_devices;
+EXPORT_SYMBOL(reset_pcie_devices);
+static int __init set_reset_pcie_devices(char *str)
+{
+	reset_pcie_devices = 1;
+	return 1;
+}
+__setup("reset_pcie_devices", set_reset_pcie_devices);
+
+static void __devinit quirk_pcie_device_reset(struct pci_dev *dev)
+{
+	struct pci_bus *subordinate;
+	struct pci_dev *child;
+	u16 ctrl;
+
+	if (!reset_pcie_devices || !pci_is_pcie(dev) || !dev->subordinate ||
+	    ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
+	     (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
+		return;
+
+	subordinate = dev->subordinate;
+	list_for_each_entry(child, &subordinate->devices, bus_list) {
+		if ((child->pcie_type == PCI_EXP_TYPE_UPSTREAM) ||
+		    (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) ||
+		    ((child->class >> 16) == PCI_BASE_CLASS_DISPLAY))
+		/* Don't reset switch, bridge, VGA device */
+		return;
+	}
+
+	dev_info(&dev->dev, "Reset Secondary bus\n");
+
+	list_for_each_entry(child, &subordinate->devices, bus_list) {
+		dev_info(&child->dev, "save state\n");
+		pci_save_state(child);
+	}
+
+	/* Assert Secondary Bus Reset */
+	pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl);
+	ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+
+	msleep(2);
+
+	/* De-assert Secondary Bus Reset */
+	ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+
+	msleep(200);
+
+	list_for_each_entry(child, &subordinate->devices, bus_list) {
+		dev_info(&child->dev, "restore state\n");
+		pci_restore_state(child);
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_pcie_device_reset);
+
+/*
   * Decoding should be disabled for a PCI device during BAR sizing to avoid
   * conflict. But doing so may cause problems on host bridge and perhaps other
   * key system devices. For devices that need to have mmio decoding always-on,
#3 lore raw
Quoted 11 lines · Takao Indoh

Hi Vivek,

Quoted 8 lines · Vivek Goyal
Quoted 6 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Quoted 8 lines
Quoted 4 lines

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

"reset_devices" is used for each driver to reset their own device, and this patch resets all devices forcibly, so I thought they were different things.

Yes reset_devices currently is used for driver to reset its device. I thought one could very well extend its reach to reset pci express devices at bus level.

Having them separate is not going to be much useful from kdump perspective. We will end up passing both reset_devices and reset_pcie_devices to second kernel whill lead to bus level reset as well as device level reset.

Ideal situation would be that somehow detect that bus level reset has been done and skip device level reset (assuming bus level reset obviates the need of device level reset, please correct me if that's not the case).

After pcie reset, can we store the state in a variable and drivers can use that variable to check if PCIe level reset was done or not. If yes, skip device level reset (Assuming driver knows that device is on a PCIe slot).

In that case we will not have to introduce new kernel command line, and also avoid double reset?

Thanks
Vivek

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#4 lore raw
Quoted 34 lines · Vivek Goyal
Quoted 11 lines · Takao Indoh

Hi Vivek,

Quoted 8 lines · Vivek Goyal
Quoted 6 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Quoted 8 lines
Quoted 4 lines

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

"reset_devices" is used for each driver to reset their own device, and this patch resets all devices forcibly, so I thought they were different things.

Yes reset_devices currently is used for driver to reset its device. I thought one could very well extend its reach to reset pci express devices at bus level.

Having them separate is not going to be much useful from kdump perspective. We will end up passing both reset_devices and reset_pcie_devices to second kernel whill lead to bus level reset as well as device level reset.

Ideal situation would be that somehow detect that bus level reset has been done and skip device level reset (assuming bus level reset obviates the need of device level reset, please correct me if that's not the case).

Quoted 7 lines

After pcie reset, can we store the state in a variable and drivers can use that variable to check if PCIe level reset was done or not. If yes, skip device level reset (Assuming driver knows that device is on a PCIe slot).

In that case we will not have to introduce new kernel command line, and also avoid double reset?

Actually I'm not sure whether the driver does not need to do their reset after bus level reset, but I agree with you, now I'm thinking that using reset_devices is better rather than adding narrow one which is limited to PCI express, otherwise we may have to add new parameter every time when adding new reset method, such as reset_pcie_devices, reset_pci_legacy_devices, etc.

Thanks,
Takao Indoh

#5 lore raw
In reply to Vivek Goyal
Quoted 34 lines · Vivek Goyal
Quoted 11 lines · Takao Indoh

Hi Vivek,

Quoted 8 lines · Vivek Goyal
Quoted 6 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Quoted 8 lines
Quoted 4 lines

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

"reset_devices" is used for each driver to reset their own device, and this patch resets all devices forcibly, so I thought they were different things.

Yes reset_devices currently is used for driver to reset its device. I thought one could very well extend its reach to reset pci express devices at bus level.

Having them separate is not going to be much useful from kdump perspective. We will end up passing both reset_devices and reset_pcie_devices to second kernel whill lead to bus level reset as well as device level reset.

Ideal situation would be that somehow detect that bus level reset has been done and skip device level reset (assuming bus level reset obviates the need of device level reset, please correct me if that's not the case).

Quoted 7 lines

After pcie reset, can we store the state in a variable and drivers can use that variable to check if PCIe level reset was done or not. If yes, skip device level reset (Assuming driver knows that device is on a PCIe slot).

In that case we will not have to introduce new kernel command line, and also avoid double reset?

I found a problem when testing my patch on some machines.

Originally there are two problems in kdump kernel when iommu is enabled; DMAR error and PCI SERR. I thought they are fixed by my patch, but I noticed that PCI SERR is still detected after applying the patch. It seems that something happens when Interrupt Remapping is initialized in kdump kernel.

Therefore resetting devices has to be done before enable_IR() is called. I have three ideas for it.

(i) Resetting devices in 1st kernel(panic kernel)
We can reset devices before jumping into 2nd kernel. Of course it may be dangerous to scan pci device tree and call PCI functions in panic'd kernel. Beforehand we need to collect device information so that only minimal code could run on panic.

(ii) Resetting devices in purgatory
It seems to be be appropriate place to do this, but I'm not sure where I can save/restore PCI config when resetting devices in purgatory.

(iii) Resetting devices in 2nd kernel(kdump kernel) Important point is to do reset before enable_IR() is called as I wrote above. I think I should add new function to do reset into arch/x86/pci/early.c and call it in setup_arch like early_dump_pci_devices() or early_quirks().

Any comments?

Thanks,
Takao Indoh

#6 lore raw
Quoted 57 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Takao Indoh
Sent: Wednesday, September 05, 2012 8:10 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Ishii, Hironobu/石井 宏延; [email protected]
Subject: Re: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump with iommu

Quoted 8 lines · Vivek Goyal
Quoted 7 lines · Takao Indoh

Hi Vivek,

Quoted 4 lines · Vivek Goyal
Quoted 3 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets

PCIe

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe

root

Quoted 15 lines
Quoted 10 lines
Quoted 6 lines
Quoted 1 line

port and downstream port to reset its downstream endpoint.

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

"reset_devices" is used for each driver to reset their own device, and this patch resets all devices forcibly, so I thought they were different things.

Yes reset_devices currently is used for driver to reset its device. I thought one could very well extend its reach to reset pci express devices at bus level.

Quoted 6 lines

Having them separate is not going to be much useful from kdump perspective. We will end up passing both reset_devices and reset_pcie_devices to second kernel whill lead to bus level reset as well as device level reset.

Ideal situation would be that somehow detect that bus level reset has

been

Quoted 10 lines

done and skip device level reset (assuming bus level reset obviates the need of device level reset, please correct me if that's not the case).

After pcie reset, can we store the state in a variable and drivers can use that variable to check if PCIe level reset was done or not. If yes, skip device level reset (Assuming driver knows that device is on a PCIe slot).

In that case we will not have to introduce new kernel command line, and also avoid double reset?

Quoted 7 lines

I found a problem when testing my patch on some machines.

Originally there are two problems in kdump kernel when iommu is enabled; DMAR error and PCI SERR. I thought they are fixed by my patch, but I noticed that PCI SERR is still detected after applying the patch. It seems that something happens when Interrupt Remapping is initialized in kdump kernel.

I'm not sure, but I guess the PCI SERR might be caused as follows.

- The 1st kernel enables interrupt remapping. The MSI(-X) address and data registers of PCI devices are programmed in remappable format.

- At the beginning of 2nd kernel, interrupt remapping is still active. And then it is disabled by enable_IR() function for initialization.

- PCI device generate an interrupt. At this moment, interrupt remapping is not enabled yet. On the other hand, MSI(-X) address and data of this interrupt is in remappable format because those are programmed by 1st kernel. I guess this might be a cause of PCI SERR.

I guess clearing command register or disabling MSI before interrupt remapping initialization in 2nd kernel might solve the PCI SERR problem.

Regards,
Kenji Kaneshige

Quoted 30 lines

Therefore resetting devices has to be done before enable_IR() is called. I have three ideas for it.

(i) Resetting devices in 1st kernel(panic kernel)
We can reset devices before jumping into 2nd kernel. Of course it may be dangerous to scan pci device tree and call PCI functions in panic'd kernel. Beforehand we need to collect device information so that only minimal code could run on panic.

(ii) Resetting devices in purgatory
It seems to be be appropriate place to do this, but I'm not sure where I can save/restore PCI config when resetting devices in purgatory.

(iii) Resetting devices in 2nd kernel(kdump kernel) Important point is to do reset before enable_IR() is called as I wrote above. I think I should add new function to do reset into arch/x86/pci/early.c and call it in setup_arch like early_dump_pci_devices() or early_quirks().

Any comments?

Thanks,
Takao Indoh

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#7 lore raw
Quoted 73 lines · Kenji
Quoted 57 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Takao Indoh
Sent: Wednesday, September 05, 2012 8:10 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Ishii, Hironobu/石井 宏延; [email protected]
Subject: Re: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump with iommu

Quoted 8 lines · Vivek Goyal
Quoted 7 lines · Takao Indoh

Hi Vivek,

Quoted 4 lines · Vivek Goyal
Quoted 3 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets

PCIe

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe

root

Quoted 15 lines
Quoted 10 lines
Quoted 6 lines
Quoted 1 line

port and downstream port to reset its downstream endpoint.

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

"reset_devices" is used for each driver to reset their own device, and this patch resets all devices forcibly, so I thought they were different things.

Yes reset_devices currently is used for driver to reset its device. I thought one could very well extend its reach to reset pci express devices at bus level.

Quoted 6 lines

Having them separate is not going to be much useful from kdump perspective. We will end up passing both reset_devices and reset_pcie_devices to second kernel whill lead to bus level reset as well as device level reset.

Ideal situation would be that somehow detect that bus level reset has

been

Quoted 10 lines

done and skip device level reset (assuming bus level reset obviates the need of device level reset, please correct me if that's not the case).

After pcie reset, can we store the state in a variable and drivers can use that variable to check if PCIe level reset was done or not. If yes, skip device level reset (Assuming driver knows that device is on a PCIe slot).

In that case we will not have to introduce new kernel command line, and also avoid double reset?

Quoted 7 lines

I found a problem when testing my patch on some machines.

Originally there are two problems in kdump kernel when iommu is enabled; DMAR error and PCI SERR. I thought they are fixed by my patch, but I noticed that PCI SERR is still detected after applying the patch. It seems that something happens when Interrupt Remapping is initialized in kdump kernel.

I'm not sure, but I guess the PCI SERR might be caused as follows.

- The 1st kernel enables interrupt remapping. The MSI(-X) address and data registers of PCI devices are programmed in remappable format.

- At the beginning of 2nd kernel, interrupt remapping is still active. And then it is disabled by enable_IR() function for initialization.

Quoted 7 lines

- PCI device generate an interrupt. At this moment, interrupt remapping is not enabled yet. On the other hand, MSI(-X) address and data of this interrupt is in remappable format because those are programmed by 1st kernel. I guess this might be a cause of PCI SERR.

I guess clearing command register or disabling MSI before interrupt remapping initialization in 2nd kernel might solve the PCI SERR problem.

Thank you for your comment. That makes sense.

Though I think clearing bus master bit is enough, do you think I need to clear all command register bit not only bus master?

Thanks,
Takao Indoh

Quoted 36 lines

Regards,
Kenji Kaneshige

Quoted 30 lines

Therefore resetting devices has to be done before enable_IR() is called. I have three ideas for it.

(i) Resetting devices in 1st kernel(panic kernel)
We can reset devices before jumping into 2nd kernel. Of course it may be dangerous to scan pci device tree and call PCI functions in panic'd kernel. Beforehand we need to collect device information so that only minimal code could run on panic.

(ii) Resetting devices in purgatory
It seems to be be appropriate place to do this, but I'm not sure where I can save/restore PCI config when resetting devices in purgatory.

(iii) Resetting devices in 2nd kernel(kdump kernel) Important point is to do reset before enable_IR() is called as I wrote above. I think I should add new function to do reset into arch/x86/pci/early.c and call it in setup_arch like early_dump_pci_devices() or early_quirks().

Any comments?

Thanks,
Takao Indoh

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#8 lore raw
Quoted 100 lines

-----Original Message-----
From: Takao Indoh [mailto:[email protected]]
Sent: Monday, September 10, 2012 3:35 PM
To: Kaneshige, Kenji/金重 憲治
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Ishii, Hironobu/石井 宏延; [email protected]
Subject: Re: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump with iommu

Quoted 7 lines · Kenji
Quoted 7 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Takao Indoh
Sent: Wednesday, September 05, 2012 8:10 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected];

Ishii,

Quoted 2 lines
Quoted 2 lines

Hironobu/石井 宏延; [email protected]
Subject: Re: [RFC][PATCH] Reset PCIe devices to address DMA problem on

kdump

Quoted 6 lines
Quoted 6 lines

with iommu

Quoted 3 lines · Vivek Goyal
Quoted 2 lines · Takao Indoh

Hi Vivek,

Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines · Vivek Goyal
Quoted 3 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets

PCIe

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

devices at boot time to address DMA problem on kdump with iommu.

When

Quoted 10 lines
Quoted 10 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

this parameter is specified, a hot reset is triggered on each PCIe

root

Quoted 8 lines
Quoted 8 lines
Quoted 6 lines
Quoted 1 line

port and downstream port to reset its downstream endpoint.

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

"reset_devices" is used for each driver to reset their own device,

and

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

this patch resets all devices forcibly, so I thought they were different things.

Yes reset_devices currently is used for driver to reset its device.

I

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

thought one could very well extend its reach to reset pci express devices at bus level.

Having them separate is not going to be much useful from kdump perspective. We will end up passing both reset_devices and reset_pcie_devices to second kernel whill lead to bus level reset as

well

Quoted 5 lines
Quoted 5 lines
Quoted 3 lines

as device level reset.

Ideal situation would be that somehow detect that bus level reset has

been

Quoted 1 line

done and skip device level reset (assuming bus level reset obviates

the

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

need of device level reset, please correct me if that's not the case).

After pcie reset, can we store the state in a variable and drivers can use that variable to check if PCIe level reset was done or not. If yes, skip device level reset (Assuming driver knows that device is on a PCIe slot).

In that case we will not have to introduce new kernel command line,

and

Quoted 8 lines
Quoted 8 lines
Quoted 1 line

also avoid double reset?

I found a problem when testing my patch on some machines.

Originally there are two problems in kdump kernel when iommu is enabled; DMAR error and PCI SERR. I thought they are fixed by my patch, but I noticed that PCI SERR is still detected after applying the patch. It seems that something happens when Interrupt Remapping is initialized

in

Quoted 4 lines
Quoted 1 line

kdump kernel.

I'm not sure, but I guess the PCI SERR might be caused as follows.

Quoted 8 lines

- The 1st kernel enables interrupt remapping. The MSI(-X) address and data registers of PCI devices are programmed in remappable format.

- At the beginning of 2nd kernel, interrupt remapping is still active. And then it is disabled by enable_IR() function for initialization.

- PCI device generate an interrupt. At this moment, interrupt remapping is not enabled yet. On the other hand, MSI(-X) address and data of

this

Quoted 3 lines

interrupt is in remappable format because those are programmed by 1st kernel. I guess this might be a cause of PCI SERR.

Quoted 8 lines
Quoted 2 lines

I guess clearing command register or disabling MSI before interrupt remapping initialization in 2nd kernel might solve the PCI SERR problem.

Thank you for your comment. That makes sense.

Though I think clearing bus master bit is enough, do you think I need to clear
all command register bit not only bus master?

I thought clearing bus master bit. But we might also need to set the disable INTx bit.

It would not be needed if we can reset devices before interrupt remapping initialization. I guess resetting devices before interrupt remapping initialization would need complex code change and be difficult to implement. If so, clearing bus master bit would be one of the alternative solution against PCI SERR issue.

Regards,
Kenji Kaneshige

Quoted 43 lines

Thanks,
Takao Indoh

Quoted 10 lines

Regards,
Kenji Kaneshige

Quoted 6 lines

Therefore resetting devices has to be done before enable_IR() is called. I have three ideas for it.

(i) Resetting devices in 1st kernel(panic kernel)
We can reset devices before jumping into 2nd kernel. Of course it

may

Quoted 15 lines
Quoted 15 lines

be dangerous to scan pci device tree and call PCI functions in panic'd kernel. Beforehand we need to collect device information so that only minimal code could run on panic.

(ii) Resetting devices in purgatory
It seems to be be appropriate place to do this, but I'm not sure where I can save/restore PCI config when resetting devices in purgatory.

(iii) Resetting devices in 2nd kernel(kdump kernel) Important point is to do reset before enable_IR() is called as I wrote above. I think I should add new function to do reset into arch/x86/pci/early.c and call it in setup_arch like early_dump_pci_devices() or early_quirks().

Quoted 7 lines
Quoted 7 lines

Any comments?

Thanks,
Takao Indoh

--
To unsubscribe from this list: send the line "unsubscribe linux-pci"

in

Quoted 4 lines
Quoted 2 lines

the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#9 lore raw
In reply to Takao Indoh
Quoted 64 lines · Takao Indoh
Quoted 34 lines · Vivek Goyal
Quoted 11 lines · Takao Indoh

Hi Vivek,

Quoted 8 lines · Vivek Goyal
Quoted 6 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Quoted 8 lines
Quoted 4 lines

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

"reset_devices" is used for each driver to reset their own device, and this patch resets all devices forcibly, so I thought they were different things.

Yes reset_devices currently is used for driver to reset its device. I thought one could very well extend its reach to reset pci express devices at bus level.

Having them separate is not going to be much useful from kdump perspective. We will end up passing both reset_devices and reset_pcie_devices to second kernel whill lead to bus level reset as well as device level reset.

Ideal situation would be that somehow detect that bus level reset has been done and skip device level reset (assuming bus level reset obviates the need of device level reset, please correct me if that's not the case).

Quoted 7 lines

After pcie reset, can we store the state in a variable and drivers can use that variable to check if PCIe level reset was done or not. If yes, skip device level reset (Assuming driver knows that device is on a PCIe slot).

In that case we will not have to introduce new kernel command line, and also avoid double reset?

I found a problem when testing my patch on some machines.

Originally there are two problems in kdump kernel when iommu is enabled; DMAR error and PCI SERR. I thought they are fixed by my patch, but I noticed that PCI SERR is still detected after applying the patch. It seems that something happens when Interrupt Remapping is initialized in kdump kernel.

Therefore resetting devices has to be done before enable_IR() is called. I have three ideas for it.

(i) Resetting devices in 1st kernel(panic kernel)
We can reset devices before jumping into 2nd kernel. Of course it may be dangerous to scan pci device tree and call PCI functions in panic'd kernel. Beforehand we need to collect device information so that only minimal code could run on panic.

(ii) Resetting devices in purgatory
It seems to be be appropriate place to do this, but I'm not sure where I can save/restore PCI config when resetting devices in purgatory.

Quoted 5 lines

(iii) Resetting devices in 2nd kernel(kdump kernel) Important point is to do reset before enable_IR() is called as I wrote above. I think I should add new function to do reset into arch/x86/pci/early.c and call it in setup_arch like early_dump_pci_devices() or early_quirks().

I would not claim that I understand hte PCI SERR issue. But whatever resettings needs to happen, should happen early in second kernel.

Doing it in first kernel is not a good idea as it is crashed kernel and we want to as little as possible.

Doing it in purgatory is not a good idea either as purgatory does not konw anything about kernel as such. We don't want to bloat purgatory with reset code and embedding the device knowledge there.

Keeping it in second kernel makes sense so that code remains with kernel and can be maintained there.

Thanks
Vivek

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#10 lore raw
Quoted 77 lines · Vivek Goyal
Quoted 64 lines · Takao Indoh
Quoted 34 lines · Vivek Goyal
Quoted 11 lines · Takao Indoh

Hi Vivek,

Quoted 8 lines · Vivek Goyal
Quoted 6 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Quoted 8 lines
Quoted 4 lines

Hi Takao,

Why not use existing "reset_devices" parameter instead of introducing a new one?

"reset_devices" is used for each driver to reset their own device, and this patch resets all devices forcibly, so I thought they were different things.

Yes reset_devices currently is used for driver to reset its device. I thought one could very well extend its reach to reset pci express devices at bus level.

Having them separate is not going to be much useful from kdump perspective. We will end up passing both reset_devices and reset_pcie_devices to second kernel whill lead to bus level reset as well as device level reset.

Ideal situation would be that somehow detect that bus level reset has been done and skip device level reset (assuming bus level reset obviates the need of device level reset, please correct me if that's not the case).

Quoted 7 lines

After pcie reset, can we store the state in a variable and drivers can use that variable to check if PCIe level reset was done or not. If yes, skip device level reset (Assuming driver knows that device is on a PCIe slot).

In that case we will not have to introduce new kernel command line, and also avoid double reset?

I found a problem when testing my patch on some machines.

Originally there are two problems in kdump kernel when iommu is enabled; DMAR error and PCI SERR. I thought they are fixed by my patch, but I noticed that PCI SERR is still detected after applying the patch. It seems that something happens when Interrupt Remapping is initialized in kdump kernel.

Therefore resetting devices has to be done before enable_IR() is called. I have three ideas for it.

(i) Resetting devices in 1st kernel(panic kernel)
We can reset devices before jumping into 2nd kernel. Of course it may be dangerous to scan pci device tree and call PCI functions in panic'd kernel. Beforehand we need to collect device information so that only minimal code could run on panic.

(ii) Resetting devices in purgatory
It seems to be be appropriate place to do this, but I'm not sure where I can save/restore PCI config when resetting devices in purgatory.

Quoted 5 lines

(iii) Resetting devices in 2nd kernel(kdump kernel) Important point is to do reset before enable_IR() is called as I wrote above. I think I should add new function to do reset into arch/x86/pci/early.c and call it in setup_arch like early_dump_pci_devices() or early_quirks().

I would not claim that I understand hte PCI SERR issue. But whatever resettings needs to happen, should happen early in second kernel.

Doing it in first kernel is not a good idea as it is crashed kernel and we want to as little as possible.

Quoted 6 lines

Doing it in purgatory is not a good idea either as purgatory does not konw anything about kernel as such. We don't want to bloat purgatory with reset code and embedding the device knowledge there.

Keeping it in second kernel makes sense so that code remains with kernel and can be maintained there.

I'll post new patch which clears bus master bit and resets devices in second kernel.

As to the boot parameter to enable this function, you suggested using reset_devices. I found that on a certain platform resetting devices caused PCIe error due to a hardware bug. Therefore I think we need new parameter apart from reset_devices to disable this function on such a machine.

Thanks,
Takao Indoh

#11 lore raw

On Tue, Sep 11, 2012 at 07:32:35PM +0900, Takao Indoh wrote:

[..]

Quoted 8 lines

I'll post new patch which clears bus master bit and resets devices in second kernel.

As to the boot parameter to enable this function, you suggested using reset_devices. I found that on a certain platform resetting devices caused PCIe error due to a hardware bug. Therefore I think we need new parameter apart from reset_devices to disable this function on such a machine.

Can you explain a bit more how the error happens. I still don't think that because of a bug in a platform somewhere we should be introducing a separate command line parameter and not reuse the exisiting one. Also you have not explained what's the bug and how a new parameter will avoid the bug.

Thanks
Vivek

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#12 lore raw
Quoted 12 lines · Vivek Goyal

On Tue, Sep 11, 2012 at 07:32:35PM +0900, Takao Indoh wrote:

[..]

Quoted 8 lines

I'll post new patch which clears bus master bit and resets devices in second kernel.

As to the boot parameter to enable this function, you suggested using reset_devices. I found that on a certain platform resetting devices caused PCIe error due to a hardware bug. Therefore I think we need new parameter apart from reset_devices to disable this function on such a machine.

Quoted 5 lines

Can you explain a bit more how the error happens. I still don't think that because of a bug in a platform somewhere we should be introducing a separate command line parameter and not reuse the exisiting one. Also you have not explained what's the bug and how a new parameter will avoid the bug.

The bug I mentioned is that ACS Violation occurs at PCIe switch when reading PCI configuration after device reset. I got information that this violation is caused by PCIe switch bug. The machine becomes fatal status by this error.

The reason why I try to introduce new parameter is that I want to avoid regression by this patch. Let's say this patch was included in kernel and its reset function was enabled by reset_devices as you said. AFAIK reset_devices is always needed for kdump, so it means that devices are always reset at kdump boot time. It causes a regression that system always becomes abnormal status when we run kdump on the machine which has a bug I mentioned.

To avoid this regression, I want to separate reset_devices from this reset function. Or how about this?
- if user specify reset_devices, devices are reset by this patch, as you said.
- To avoid a regression I said, add new parameter like "pci=noreset". If this parameter is specified, the reset function I add is disabled and we can avoid regression.

Thanks,
Takao Indoh

#13 lore raw
Quoted 32 lines · Takao Indoh
Quoted 12 lines · Vivek Goyal

On Tue, Sep 11, 2012 at 07:32:35PM +0900, Takao Indoh wrote:

[..]

Quoted 8 lines

I'll post new patch which clears bus master bit and resets devices in second kernel.

As to the boot parameter to enable this function, you suggested using reset_devices. I found that on a certain platform resetting devices caused PCIe error due to a hardware bug. Therefore I think we need new parameter apart from reset_devices to disable this function on such a machine.

Quoted 5 lines

Can you explain a bit more how the error happens. I still don't think that because of a bug in a platform somewhere we should be introducing a separate command line parameter and not reuse the exisiting one. Also you have not explained what's the bug and how a new parameter will avoid the bug.

The bug I mentioned is that ACS Violation occurs at PCIe switch when reading PCI configuration after device reset. I got information that this violation is caused by PCIe switch bug. The machine becomes fatal status by this error.

The reason why I try to introduce new parameter is that I want to avoid regression by this patch. Let's say this patch was included in kernel and its reset function was enabled by reset_devices as you said. AFAIK reset_devices is always needed for kdump, so it means that devices are always reset at kdump boot time. It causes a regression that system always becomes abnormal status when we run kdump on the machine which has a bug I mentioned.

Quoted 7 lines

To avoid this regression, I want to separate reset_devices from this reset function. Or how about this?
- if user specify reset_devices, devices are reset by this patch, as you said.
- To avoid a regression I said, add new parameter like "pci=noreset". If this parameter is specified, the reset function I add is disabled and we can avoid regression.

Can we identify that particular switch in code and not reset it in code. Introducing new paramenters to avoid bugs really feels odd.

Also, what was the conclusion to avoid double reset. I am assuming that we don't want to do bus level reset as well as driver level reset based on reset_devices.

Thanks
Vivek

#14 lore raw
Quoted 41 lines · Vivek Goyal
Quoted 32 lines · Takao Indoh
Quoted 12 lines · Vivek Goyal

On Tue, Sep 11, 2012 at 07:32:35PM +0900, Takao Indoh wrote:

[..]

Quoted 8 lines

I'll post new patch which clears bus master bit and resets devices in second kernel.

As to the boot parameter to enable this function, you suggested using reset_devices. I found that on a certain platform resetting devices caused PCIe error due to a hardware bug. Therefore I think we need new parameter apart from reset_devices to disable this function on such a machine.

Quoted 5 lines

Can you explain a bit more how the error happens. I still don't think that because of a bug in a platform somewhere we should be introducing a separate command line parameter and not reuse the exisiting one. Also you have not explained what's the bug and how a new parameter will avoid the bug.

The bug I mentioned is that ACS Violation occurs at PCIe switch when reading PCI configuration after device reset. I got information that this violation is caused by PCIe switch bug. The machine becomes fatal status by this error.

The reason why I try to introduce new parameter is that I want to avoid regression by this patch. Let's say this patch was included in kernel and its reset function was enabled by reset_devices as you said. AFAIK reset_devices is always needed for kdump, so it means that devices are always reset at kdump boot time. It causes a regression that system always becomes abnormal status when we run kdump on the machine which has a bug I mentioned.

Quoted 7 lines

To avoid this regression, I want to separate reset_devices from this reset function. Or how about this?
- if user specify reset_devices, devices are reset by this patch, as you said.
- To avoid a regression I said, add new parameter like "pci=noreset". If this parameter is specified, the reset function I add is disabled and we can avoid regression.

Quoted 2 lines

Can we identify that particular switch in code and not reset it in code. Introducing new paramenters to avoid bugs really feels odd.

Maybe we can do it using PCI quirk or DMI quirk as Konrad and Don said. But I'm still thinking whether I can add boot parameter or something to disable reset function so that we can use it as workaround untill we add quirk when we find such a buggy hardware.

Quoted 3 lines

Also, what was the conclusion to avoid double reset. I am assuming that we don't want to do bus level reset as well as driver level reset based on reset_devices.

I don't have a good idea to do it yet. Maybe we need to write bus:slot:func information to somewhere when we reset device.

Thanks,
Takao Indoh

#15 lore raw
In reply to Takao Indoh
Quoted 5 lines

As to the boot parameter to enable this function, you suggested using reset_devices. I found that on a certain platform resetting devices caused PCIe error due to a hardware bug. Therefore I think we need new parameter apart from reset_devices to disable this function on such a machine.

Wouldn't a DMI quirk be better for this? That way the second kernel internally would know not to do this.

#16 lore raw
Quoted 8 lines · Konrad Rzeszutek Wilk
Quoted 5 lines

As to the boot parameter to enable this function, you suggested using reset_devices. I found that on a certain platform resetting devices caused PCIe error due to a hardware bug. Therefore I think we need new parameter apart from reset_devices to disable this function on such a machine.

Wouldn't a DMI quirk be better for this? That way the second kernel internally would know not to do this.

That sounds good. I'll try it, thanks.

Thanks,
Takao Indoh

#17 lore raw
In reply to Konrad Rzeszutek Wilk
Quoted 6 lines · Konrad Rzeszutek Wilk
Quoted 5 lines

As to the boot parameter to enable this function, you suggested using reset_devices. I found that on a certain platform resetting devices caused PCIe error due to a hardware bug. Therefore I think we need new parameter apart from reset_devices to disable this function on such a machine.

Quoted 6 lines

Wouldn't a DMI quirk be better for this? That way the second kernel internally would know not to do this.
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

a DMI quirk for a PCIe switch? pci-quirk maybe? there is a hook in per-device pci reset code path, which could be setup for such a case.

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#18 lore raw
Quoted 13 lines · Don Dutile
Quoted 6 lines · Konrad Rzeszutek Wilk
Quoted 5 lines

As to the boot parameter to enable this function, you suggested using reset_devices. I found that on a certain platform resetting devices caused PCIe error due to a hardware bug. Therefore I think we need new parameter apart from reset_devices to disable this function on such a machine.

Quoted 6 lines

Wouldn't a DMI quirk be better for this? That way the second kernel internally would know not to do this.
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Quoted 3 lines

a DMI quirk for a PCIe switch? pci-quirk maybe? there is a hook in per-device pci reset code path, which could be setup for such a case.

Yep, I think early-quirk is better.

Thanks,
Takao Indoh

#19 lore raw
In reply to Takao Indoh
Quoted 26 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Background:
A kdump problem about DMA has been discussed for a long time. That is, when a kernel is switched to the kdump kernel DMA derived from first kernel affects second kernel. Recently this problem surfaces when iommu is used for PCI passthrough on KVM guest. In the case of the machine I use, when intel_iommu=on is specified, DMAR error is detected in kdump kernel and PCI SERR is also detected. Finally kdump fails because some devices does not work correctly.

The root cause is that ongoing DMA from first kernel causes DMAR fault because page table of DMAR is initialized while kdump kernel is booting up. Therefore to address this problem DMA needs to be stopped before DMAR is initialized at kdump kernel boot time. By this patch, PCIe devices are reset by hot reset and its DMA is stopped when reset_pcie_devices is specified. One problem of this solution is that VGA is reset and the monitor blacks out when the link between the port and VGA controller was reset. So this patch does not reset the port whose child endpoint is VGA device.

Quoted 4 lines

Any comments would be appreciated.

---

Have you considered something less disruptive such as clearing the Master Enable in each endpoint's PCI Command Register ?
That should prevent DMA transactions from endpoints during the kdump and kexec, and when the driver for the device gets reconfigured, Master Enable will be set back on, but after the driver has had the opportunity to do a device-specific reset.

- Don

Quoted 91 lines
  Documentation/kernel-parameters.txt |    4 +
  drivers/pci/quirks.c                |   59 ++++++++++++++++++++++++++
  2 files changed, 63 insertions(+)
Documentation/kernel-parameters.txt +4 -0
index e714a02..e694e9f 100644
@@ -2489,6 +2489,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
  	reset_devices	[KNL] Force drivers to reset the underlying device
  			during initialization.
 
+	reset_pcie_devices
+			[PCIE] Reset PCIe endpoint at boot time by sending a
+			hot reset to root port and downstream port
+
  	resume=		[SWSUSP]
  			Specify the partition device for software suspend
  			Format:
drivers/pci/quirks.c +59 -1
index 5155317..7f7fc02 100644
@@ -32,6 +32,65 @@
  #include "pci.h"
 
  /*
+ * Reset PCIe endpoint by sending a hot reset to root port and downstream port
+ */
+unsigned int reset_pcie_devices;
+EXPORT_SYMBOL(reset_pcie_devices);
+static int __init set_reset_pcie_devices(char *str)
+{
+	reset_pcie_devices = 1;
+	return 1;
+}
+__setup("reset_pcie_devices", set_reset_pcie_devices);
+
+static void __devinit quirk_pcie_device_reset(struct pci_dev *dev)
+{
+	struct pci_bus *subordinate;
+	struct pci_dev *child;
+	u16 ctrl;
+
+	if (!reset_pcie_devices || !pci_is_pcie(dev) || !dev->subordinate ||
+	    ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT)&&
+	     (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
+		return;
+
+	subordinate = dev->subordinate;
+	list_for_each_entry(child,&subordinate->devices, bus_list) {
+		if ((child->pcie_type == PCI_EXP_TYPE_UPSTREAM) ||
+		    (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) ||
+		    ((child->class>>  16) == PCI_BASE_CLASS_DISPLAY))
+		/* Don't reset switch, bridge, VGA device */
+		return;
+	}
+
+	dev_info(&dev->dev, "Reset Secondary bus\n");
+
+	list_for_each_entry(child,&subordinate->devices, bus_list) {
+		dev_info(&child->dev, "save state\n");
+		pci_save_state(child);
+	}
+
+	/* Assert Secondary Bus Reset */
+	pci_read_config_word(dev, PCI_BRIDGE_CONTROL,&ctrl);
+	ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+
+	msleep(2);
+
+	/* De-assert Secondary Bus Reset */
+	ctrl&= ~PCI_BRIDGE_CTL_BUS_RESET;
+	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
+
+	msleep(200);
+
+	list_for_each_entry(child,&subordinate->devices, bus_list) {
+		dev_info(&child->dev, "restore state\n");
+		pci_restore_state(child);
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_pcie_device_reset);
+
+/*
   * Decoding should be disabled for a PCI device during BAR sizing to avoid
   * conflict. But doing so may cause problems on host bridge and perhaps other
   * key system devices. For devices that need to have mmio decoding always-on,
 
--
Quoted 3 lines

To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#20 lore raw

Hi Don,

Quoted 29 lines · Don Dutile
Quoted 28 lines · Takao Indoh

Hi all,

This patch adds kernel parameter "reset_pcie_devices" which resets PCIe devices at boot time to address DMA problem on kdump with iommu. When this parameter is specified, a hot reset is triggered on each PCIe root port and downstream port to reset its downstream endpoint.

Background:
A kdump problem about DMA has been discussed for a long time. That is, when a kernel is switched to the kdump kernel DMA derived from first kernel affects second kernel. Recently this problem surfaces when iommu is used for PCI passthrough on KVM guest. In the case of the machine I use, when intel_iommu=on is specified, DMAR error is detected in kdump kernel and PCI SERR is also detected. Finally kdump fails because some devices does not work correctly.

The root cause is that ongoing DMA from first kernel causes DMAR fault because page table of DMAR is initialized while kdump kernel is booting up. Therefore to address this problem DMA needs to be stopped before DMAR is initialized at kdump kernel boot time. By this patch, PCIe devices are reset by hot reset and its DMA is stopped when reset_pcie_devices is specified. One problem of this solution is that VGA is reset and the monitor blacks out when the link between the port and VGA controller was reset. So this patch does not reset the port whose child endpoint is VGA device.

Any comments would be appreciated.

Quoted 8 lines
Quoted 2 lines

---

Have you considered something less disruptive such as clearing the Master Enable in each endpoint's PCI Command Register ?
That should prevent DMA transactions from endpoints during the kdump and kexec, and when the driver for the device gets reconfigured, Master Enable will be set back on, but after the driver has had the opportunity to do a device-specific reset.

Yes, that is what I tried first. First of all I found this thread.

[PATCH] Disable Bus Master on PCI device shutdown
https://lkml.org/lkml/2012/6/6/278
original patch: http://marc.info/?l=kexec&m=133546519231295&w=2

And I thought ongoing DMA could be stopped by disabling it on kdump kernel boot, but DMAR error is still found after adding quirk below.

In this thread, AER link reset was also suggested, so I got the idea to reset root port and downstream port.

Thanks,
Takao Indoh

drivers/pci/quirks.c +16 -0
index 5155317..0e8b41a 100644
@@ -31,6 +31,22 @@
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
 #include "pci.h"
 
+static void test_pci_device_reset(struct pci_dev *dev)
+{
+	u16 pci_command;
+
+	if (!reset_devices)
+		return;
+
+	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
+	if (pci_command & PCI_COMMAND_MASTER) {
+		dev_info(&dev->dev, "DEBUG: Disable Bus Master bit\n");
+		pci_command &= ~PCI_COMMAND_MASTER;
+		pci_write_config_word(dev, PCI_COMMAND, pci_command);
+	}
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, test_pci_device_reset);
+
 /*
  * Decoding should be disabled for a PCI device during BAR sizing to avoid
  * conflict. But doing so may cause problems on host bridge and perhaps other