All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] PCI: Add quirk for 64-bit DMA on RS690 chipset
@ 2021-05-27 21:45 Mikel Rychliski
  2021-06-04 23:02 ` Bjorn Helgaas
  0 siblings, 1 reply; 5+ messages in thread
From: Mikel Rychliski @ 2021-05-27 21:45 UTC (permalink / raw)
  To: linux-pci, Bjorn Helgaas; +Cc: Mikel Rychliski

Although the AMD RS690 chipset has 64-bit DMA support, BIOS implementations
sometimes fail to configure the memory limit registers correctly.
Currently, the ahci driver has quirks to enable or disable 64-bit DMA
depending on the BIOS version (see ahci_sb600_enable_64bit() in ahci.c).
snd_hda_intel always disables 64-bit DMA with the paired SB600 chipset.

The Acer F690GVM mainboard uses this chipset and a Marvell 88E8056 NIC. The
sky2 driver attempts to use 64-bit DMA the NIC, which will not work:

	sky2 0000:02:00.0: error interrupt status=0x8
	sky2 0000:02:00.0 eth0: tx timeout
	sky2 0000:02:00.0 eth0: transmit ring 0 .. 22 report=0 done=0

Avoid the issue by configuring the memory limit registers correctly if the
BIOS failed to. If the kernel is aware of physical memory above 4GB, but
the BIOS never configured the PCI host with this information, update the
register with our value.

Signed-off-by: Mikel Rychliski <mikel@mikelr.com>
---
 drivers/pci/quirks.c    | 44 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci_ids.h |  1 +
 2 files changed, 45 insertions(+)

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index dcb229de1acb..cd98a01de908 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -5601,3 +5601,47 @@ static void apex_pci_fixup_class(struct pci_dev *pdev)
 }
 DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a,
 			       PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class);
+
+#define RS690_LOWER_TOP_OF_DRAM2	0x30
+#define RS690_LOWER_TOP_OF_DRAM2_VALID	0x1
+#define RS690_UPPER_TOP_OF_DRAM2	0x31
+#define RS690_HTIU_NB_INDEX		0xA8
+#define RS690_HTIU_NB_INDEX_WR_ENABLE	0x100
+#define RS690_HTIU_NB_DATA		0xAC
+
+/*
+ * Some BIOS implementations support RAM above 4GB, but do not configure the
+ * PCI host to respond to bus master accesses for these addresses. These
+ * implementations set the TOP_OF_DRAM_SLOT1 register correctly, so PCI DMA
+ * works as expected for addresses below 4GB.
+ *
+ * Reference: "AMD RS690 ASIC Family Register Reference Guide" (public)
+ */
+static void rs690_fix_64bit_dma(struct pci_dev *pdev)
+{
+	u32 val = 0;
+	phys_addr_t top_of_dram = __pa(high_memory - 1) + 1;
+
+	if (top_of_dram <= (1ULL << 32))
+		return;
+
+	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
+				RS690_LOWER_TOP_OF_DRAM2);
+	pci_read_config_dword(pdev, RS690_HTIU_NB_DATA, &val);
+
+	if (val)
+		return;
+
+	pci_info(pdev, "Adjusting top of DRAM to support 64-bit DMA\n");
+
+	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
+		RS690_UPPER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
+	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA, top_of_dram >> 32);
+
+	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
+		RS690_LOWER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
+	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA,
+		top_of_dram | RS690_LOWER_TOP_OF_DRAM2_VALID);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS690,
+			rs690_fix_64bit_dma);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 4c3fa5293d76..0a7fe2ed520b 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -381,6 +381,7 @@
 #define PCI_DEVICE_ID_ATI_RS400_166     0x5a32
 #define PCI_DEVICE_ID_ATI_RS400_200     0x5a33
 #define PCI_DEVICE_ID_ATI_RS480         0x5950
+#define PCI_DEVICE_ID_ATI_RS690         0x7910
 /* ATI IXP Chipset */
 #define PCI_DEVICE_ID_ATI_IXP200_IDE	0x4349
 #define PCI_DEVICE_ID_ATI_IXP200_SMBUS	0x4353
-- 
2.13.7


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

* Re: [PATCH] PCI: Add quirk for 64-bit DMA on RS690 chipset
  2021-05-27 21:45 [PATCH] PCI: Add quirk for 64-bit DMA on RS690 chipset Mikel Rychliski
@ 2021-06-04 23:02 ` Bjorn Helgaas
  2021-06-07  4:37   ` Mikel Rychliski
  0 siblings, 1 reply; 5+ messages in thread
From: Bjorn Helgaas @ 2021-06-04 23:02 UTC (permalink / raw)
  To: Mikel Rychliski; +Cc: linux-pci, Bjorn Helgaas, x86

[+cc x86]

On Thu, May 27, 2021 at 05:45:21PM -0400, Mikel Rychliski wrote:
> Although the AMD RS690 chipset has 64-bit DMA support, BIOS implementations
> sometimes fail to configure the memory limit registers correctly.

> Currently, the ahci driver has quirks to enable or disable 64-bit DMA
> depending on the BIOS version (see ahci_sb600_enable_64bit() in ahci.c).
> snd_hda_intel always disables 64-bit DMA with the paired SB600 chipset.

This patch applies to RS690.  Is there a connection between SB600 and
RS690?  Trying to figure out why the above two sentences are here.

What is the implication of this patch for ahci_sb600_enable_64bit()
and snd_hda_intel?  (BTW, "git grep snd_hda_intel" turns up no useful
pointers; a specific function name would be more useful.)

> The Acer F690GVM mainboard uses this chipset and a Marvell 88E8056 NIC. The
> sky2 driver attempts to use 64-bit DMA the NIC, which will not work:

"attempts to use 64-bit DMA the NIC" doesn't quite parse.  Maybe
"programs the NIC to use 64-bit DMA"?

> 	sky2 0000:02:00.0: error interrupt status=0x8
> 	sky2 0000:02:00.0 eth0: tx timeout
> 	sky2 0000:02:00.0 eth0: transmit ring 0 .. 22 report=0 done=0
> 
> Avoid the issue by configuring the memory limit registers correctly if the
> BIOS failed to. If the kernel is aware of physical memory above 4GB, but
> the BIOS never configured the PCI host with this information, update the
> register with our value.

I'm guessing RS690 is only applicable for x86.  We do have a bunch of
obviously x86-specific stuff in drivers/pci/quirks.c, but I think this
could probably go in arch/x86/pci/fixup.c, where it won't get compiled
for all the arches that can never use it.

Or it's conceivable it might fit in arch/x86/pci/amd_bus.c, since
there's some code there dealing with the memory map.

> Signed-off-by: Mikel Rychliski <mikel@mikelr.com>
> ---
>  drivers/pci/quirks.c    | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pci_ids.h |  1 +
>  2 files changed, 45 insertions(+)
> 
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index dcb229de1acb..cd98a01de908 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -5601,3 +5601,47 @@ static void apex_pci_fixup_class(struct pci_dev *pdev)
>  }
>  DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a,
>  			       PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class);
> +
> +#define RS690_LOWER_TOP_OF_DRAM2	0x30
> +#define RS690_LOWER_TOP_OF_DRAM2_VALID	0x1
> +#define RS690_UPPER_TOP_OF_DRAM2	0x31
> +#define RS690_HTIU_NB_INDEX		0xA8
> +#define RS690_HTIU_NB_INDEX_WR_ENABLE	0x100
> +#define RS690_HTIU_NB_DATA		0xAC
> +
> +/*
> + * Some BIOS implementations support RAM above 4GB, but do not configure the
> + * PCI host to respond to bus master accesses for these addresses. These
> + * implementations set the TOP_OF_DRAM_SLOT1 register correctly, so PCI DMA
> + * works as expected for addresses below 4GB.
> + *
> + * Reference: "AMD RS690 ASIC Family Register Reference Guide" (public)

The NB_TOP_OF_DRAM_SLOT1 section talks about incoming PCI DMA, but
unfortunately the public spec I found (P/N 43372) says nothing at all
about NB_UPPER_TOP_OF_DRAM2.

> + */
> +static void rs690_fix_64bit_dma(struct pci_dev *pdev)
> +{
> +	u32 val = 0;
> +	phys_addr_t top_of_dram = __pa(high_memory - 1) + 1;
> +
> +	if (top_of_dram <= (1ULL << 32))
> +		return;
> +
> +	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
> +				RS690_LOWER_TOP_OF_DRAM2);
> +	pci_read_config_dword(pdev, RS690_HTIU_NB_DATA, &val);
> +
> +	if (val)
> +		return;
> +
> +	pci_info(pdev, "Adjusting top of DRAM to support 64-bit DMA\n");

Maybe include the top_of_dram value in the message?

> +	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
> +		RS690_UPPER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
> +	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA, top_of_dram >> 32);
> +
> +	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
> +		RS690_LOWER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
> +	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA,
> +		top_of_dram | RS690_LOWER_TOP_OF_DRAM2_VALID);
> +}
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS690,
> +			rs690_fix_64bit_dma);
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 4c3fa5293d76..0a7fe2ed520b 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -381,6 +381,7 @@
>  #define PCI_DEVICE_ID_ATI_RS400_166     0x5a32
>  #define PCI_DEVICE_ID_ATI_RS400_200     0x5a33
>  #define PCI_DEVICE_ID_ATI_RS480         0x5950
> +#define PCI_DEVICE_ID_ATI_RS690         0x7910
>  /* ATI IXP Chipset */
>  #define PCI_DEVICE_ID_ATI_IXP200_IDE	0x4349
>  #define PCI_DEVICE_ID_ATI_IXP200_SMBUS	0x4353
> -- 
> 2.13.7
> 

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

* Re: [PATCH] PCI: Add quirk for 64-bit DMA on RS690 chipset
  2021-06-04 23:02 ` Bjorn Helgaas
@ 2021-06-07  4:37   ` Mikel Rychliski
  2021-06-11 21:48     ` [PATCH v2] " Mikel Rychliski
  0 siblings, 1 reply; 5+ messages in thread
From: Mikel Rychliski @ 2021-06-07  4:37 UTC (permalink / raw)
  To: Bjorn Helgaas; +Cc: linux-pci, Bjorn Helgaas, x86

Thanks for the review

On Friday, June 4, 2021 7:02:57 PM EDT Bjorn Helgaas wrote:
> [+cc x86]
> 
> On Thu, May 27, 2021 at 05:45:21PM -0400, Mikel Rychliski wrote:
> > Although the AMD RS690 chipset has 64-bit DMA support, BIOS
> > implementations
> > sometimes fail to configure the memory limit registers correctly.
> > 
> > Currently, the ahci driver has quirks to enable or disable 64-bit DMA
> > depending on the BIOS version (see ahci_sb600_enable_64bit() in ahci.c).
> > snd_hda_intel always disables 64-bit DMA with the paired SB600 chipset.
> 
> This patch applies to RS690.  Is there a connection between SB600 and
> RS690?  Trying to figure out why the above two sentences are here.
> 
> What is the implication of this patch for ahci_sb600_enable_64bit()
> and snd_hda_intel?  (BTW, "git grep snd_hda_intel" turns up no useful
> pointers; a specific function name would be more useful.)

The RS690 and SB600 were often (always?) installed as a pair on motherboards. 
Currently, the ahci and hda-intel drivers have quirks to disable 64-bit DMA 
for SB600. But those quirks are probably only there because the PCI host 
(RS690) used with the SB600 often has broken 64-bit DMA.

The SB600 quirks could probably be removed now. On my machine, ahci is broken 
without quirks, but either quirk by itself fixes the problem. I wasn't sure if 
a sample size of one was enough to remove the SB600 quirks though, so I just 
left them in.

I was trying to give context about why the issue was with the host controller 
and not a specific driver (other drivers only work because 64-bit DMA is 
disabled there). I'll update the message to be more clear. Unless it could be 
omitted entirely?

> > 	sky2 0000:02:00.0: error interrupt status=0x8
> > 	sky2 0000:02:00.0 eth0: tx timeout
> > 	sky2 0000:02:00.0 eth0: transmit ring 0 .. 22 report=0 done=0
> > 
> > Avoid the issue by configuring the memory limit registers correctly if the
> > BIOS failed to. If the kernel is aware of physical memory above 4GB, but
> > the BIOS never configured the PCI host with this information, update the
> > register with our value.
> 
> I'm guessing RS690 is only applicable for x86.  We do have a bunch of
> obviously x86-specific stuff in drivers/pci/quirks.c, but I think this
> could probably go in arch/x86/pci/fixup.c, where it won't get compiled
> for all the arches that can never use it.
> 
> Or it's conceivable it might fit in arch/x86/pci/amd_bus.c, since
> there's some code there dealing with the memory map.

This should only apply to x86, so I'll move to arch/x86/pci/fixup.c. I was 
hesitant to move to amd_bus.c since that runs very early, and seems to focus 
on setting up the memory map for the CPU using MSRs (along with the PCI memory 
windows). In fixup.c we can use the normal device matching for quirks.

> > Signed-off-by: Mikel Rychliski <mikel@mikelr.com>
> > ---
> > 
> >  drivers/pci/quirks.c    | 44 ++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/pci_ids.h |  1 +
> >  2 files changed, 45 insertions(+)
> > 
> > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > index dcb229de1acb..cd98a01de908 100644
> > --- a/drivers/pci/quirks.c
> > +++ b/drivers/pci/quirks.c
> > @@ -5601,3 +5601,47 @@ static void apex_pci_fixup_class(struct pci_dev
> > *pdev)> 
> >  }
> >  DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a,
> >  
> >  			       PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class);
> > 
> > +
> > +#define RS690_LOWER_TOP_OF_DRAM2	0x30
> > +#define RS690_LOWER_TOP_OF_DRAM2_VALID	0x1
> > +#define RS690_UPPER_TOP_OF_DRAM2	0x31
> > +#define RS690_HTIU_NB_INDEX		0xA8
> > +#define RS690_HTIU_NB_INDEX_WR_ENABLE	0x100
> > +#define RS690_HTIU_NB_DATA		0xAC
> > +
> > +/*
> > + * Some BIOS implementations support RAM above 4GB, but do not configure
> > the + * PCI host to respond to bus master accesses for these addresses.
> > These + * implementations set the TOP_OF_DRAM_SLOT1 register correctly,
> > so PCI DMA + * works as expected for addresses below 4GB.
> > + *
> > + * Reference: "AMD RS690 ASIC Family Register Reference Guide" (public)
> 
> The NB_TOP_OF_DRAM_SLOT1 section talks about incoming PCI DMA, but
> unfortunately the public spec I found (P/N 43372) says nothing at all
> about NB_UPPER_TOP_OF_DRAM2.

I had found it on page 2-57 (pdf page 63) in:
https://www.amd.com/system/files/TechDocs/43372_rs690_rrg_3.00o.pdf

It looks like it may have been added in a revision. If you're referring to the 
lack of behavior description, yes it doesn't explicitly call out PCI DMA. I 
guessed based on the name similarity to NB_TOP_OF_DRAM_SLOT1 and confirmed that 
DMA above 4GB works once the top of memory is corrected here.

Thanks,
Mikel

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

* [PATCH v2] PCI: Add quirk for 64-bit DMA on RS690 chipset
  2021-06-07  4:37   ` Mikel Rychliski
@ 2021-06-11 21:48     ` Mikel Rychliski
  2021-06-16 23:23       ` Bjorn Helgaas
  0 siblings, 1 reply; 5+ messages in thread
From: Mikel Rychliski @ 2021-06-11 21:48 UTC (permalink / raw)
  To: mikel; +Cc: bhelgaas, helgaas, linux-pci, x86

Although the AMD RS690 chipset has 64-bit DMA support, BIOS implementations
sometimes fail to configure the memory limit registers correctly.

The Acer F690GVM mainboard uses this chipset and a Marvell 88E8056 NIC. The
sky2 driver programs the NIC to use 64-bit DMA, which will not work:

	sky2 0000:02:00.0: error interrupt status=0x8
	sky2 0000:02:00.0 eth0: tx timeout
	sky2 0000:02:00.0 eth0: transmit ring 0 .. 22 report=0 done=0

Other drivers required by this mainboard either don't support 64-bit DMA,
or have it disabled using driver specific quirks. For example, the ahci
driver has quirks to enable or disable 64-bit DMA depending on the BIOS
version (see ahci_sb600_enable_64bit() in ahci.c). This ahci quirk matches
against the SB600 SATA controller, but the real issue is almost certainly
with the RS690 PCI host that it was commonly attached to.

To avoid this issue in all drivers with 64-bit DMA support, fix the
configuration of the PCI host. If the kernel is aware of physical memory
above 4GB, but the BIOS never configured the PCI host with this
information, update the registers with our values.

Signed-off-by: Mikel Rychliski <mikel@mikelr.com>
---
 arch/x86/pci/fixup.c    | 45 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci_ids.h |  1 +
 2 files changed, 46 insertions(+)

diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 02dc64625e64..4cc479f332ba 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -779,4 +779,49 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1571, pci_amd_enable_64bit_bar);
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x15b1, pci_amd_enable_64bit_bar);
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1601, pci_amd_enable_64bit_bar);
 
+#define RS690_LOWER_TOP_OF_DRAM2	0x30
+#define RS690_LOWER_TOP_OF_DRAM2_VALID	0x1
+#define RS690_UPPER_TOP_OF_DRAM2	0x31
+#define RS690_HTIU_NB_INDEX		0xA8
+#define RS690_HTIU_NB_INDEX_WR_ENABLE	0x100
+#define RS690_HTIU_NB_DATA		0xAC
+
+/*
+ * Some BIOS implementations support RAM above 4GB, but do not configure the
+ * PCI host to respond to bus master accesses for these addresses. These
+ * implementations set the TOP_OF_DRAM_SLOT1 register correctly, so PCI DMA
+ * works as expected for addresses below 4GB.
+ *
+ * Reference: "AMD RS690 ASIC Family Register Reference Guide" (pg. 2-57)
+ * https://www.amd.com/system/files/TechDocs/43372_rs690_rrg_3.00o.pdf
+ */
+static void rs690_fix_64bit_dma(struct pci_dev *pdev)
+{
+	u32 val = 0;
+	phys_addr_t top_of_dram = __pa(high_memory - 1) + 1;
+
+	if (top_of_dram <= (1ULL << 32))
+		return;
+
+	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
+				RS690_LOWER_TOP_OF_DRAM2);
+	pci_read_config_dword(pdev, RS690_HTIU_NB_DATA, &val);
+
+	if (val)
+		return;
+
+	pci_info(pdev, "Adjusting top of DRAM to %pa for 64-bit DMA support\n", &top_of_dram);
+
+	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
+		RS690_UPPER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
+	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA, top_of_dram >> 32);
+
+	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
+		RS690_LOWER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
+	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA,
+		top_of_dram | RS690_LOWER_TOP_OF_DRAM2_VALID);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS690,
+			rs690_fix_64bit_dma);
+
 #endif
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 4c3fa5293d76..0a7fe2ed520b 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -381,6 +381,7 @@
 #define PCI_DEVICE_ID_ATI_RS400_166     0x5a32
 #define PCI_DEVICE_ID_ATI_RS400_200     0x5a33
 #define PCI_DEVICE_ID_ATI_RS480         0x5950
+#define PCI_DEVICE_ID_ATI_RS690         0x7910
 /* ATI IXP Chipset */
 #define PCI_DEVICE_ID_ATI_IXP200_IDE	0x4349
 #define PCI_DEVICE_ID_ATI_IXP200_SMBUS	0x4353
-- 
2.13.7


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

* Re: [PATCH v2] PCI: Add quirk for 64-bit DMA on RS690 chipset
  2021-06-11 21:48     ` [PATCH v2] " Mikel Rychliski
@ 2021-06-16 23:23       ` Bjorn Helgaas
  0 siblings, 0 replies; 5+ messages in thread
From: Bjorn Helgaas @ 2021-06-16 23:23 UTC (permalink / raw)
  To: Mikel Rychliski; +Cc: bhelgaas, linux-pci, x86

On Fri, Jun 11, 2021 at 05:48:23PM -0400, Mikel Rychliski wrote:
> Although the AMD RS690 chipset has 64-bit DMA support, BIOS implementations
> sometimes fail to configure the memory limit registers correctly.
> 
> The Acer F690GVM mainboard uses this chipset and a Marvell 88E8056 NIC. The
> sky2 driver programs the NIC to use 64-bit DMA, which will not work:
> 
> 	sky2 0000:02:00.0: error interrupt status=0x8
> 	sky2 0000:02:00.0 eth0: tx timeout
> 	sky2 0000:02:00.0 eth0: transmit ring 0 .. 22 report=0 done=0
> 
> Other drivers required by this mainboard either don't support 64-bit DMA,
> or have it disabled using driver specific quirks. For example, the ahci
> driver has quirks to enable or disable 64-bit DMA depending on the BIOS
> version (see ahci_sb600_enable_64bit() in ahci.c). This ahci quirk matches
> against the SB600 SATA controller, but the real issue is almost certainly
> with the RS690 PCI host that it was commonly attached to.
> 
> To avoid this issue in all drivers with 64-bit DMA support, fix the
> configuration of the PCI host. If the kernel is aware of physical memory
> above 4GB, but the BIOS never configured the PCI host with this
> information, update the registers with our values.
> 
> Signed-off-by: Mikel Rychliski <mikel@mikelr.com>

Applied to for-linus for v5.13, thanks!

I replaced PCI_DEVICE_ID_ATI_RS690 with 0x7910 because we don't
usually add those #defines when they're only used in one place.

> ---
>  arch/x86/pci/fixup.c    | 45 +++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pci_ids.h |  1 +
>  2 files changed, 46 insertions(+)
> 
> diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
> index 02dc64625e64..4cc479f332ba 100644
> --- a/arch/x86/pci/fixup.c
> +++ b/arch/x86/pci/fixup.c
> @@ -779,4 +779,49 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1571, pci_amd_enable_64bit_bar);
>  DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x15b1, pci_amd_enable_64bit_bar);
>  DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1601, pci_amd_enable_64bit_bar);
>  
> +#define RS690_LOWER_TOP_OF_DRAM2	0x30
> +#define RS690_LOWER_TOP_OF_DRAM2_VALID	0x1
> +#define RS690_UPPER_TOP_OF_DRAM2	0x31
> +#define RS690_HTIU_NB_INDEX		0xA8
> +#define RS690_HTIU_NB_INDEX_WR_ENABLE	0x100
> +#define RS690_HTIU_NB_DATA		0xAC
> +
> +/*
> + * Some BIOS implementations support RAM above 4GB, but do not configure the
> + * PCI host to respond to bus master accesses for these addresses. These
> + * implementations set the TOP_OF_DRAM_SLOT1 register correctly, so PCI DMA
> + * works as expected for addresses below 4GB.
> + *
> + * Reference: "AMD RS690 ASIC Family Register Reference Guide" (pg. 2-57)
> + * https://www.amd.com/system/files/TechDocs/43372_rs690_rrg_3.00o.pdf
> + */
> +static void rs690_fix_64bit_dma(struct pci_dev *pdev)
> +{
> +	u32 val = 0;
> +	phys_addr_t top_of_dram = __pa(high_memory - 1) + 1;
> +
> +	if (top_of_dram <= (1ULL << 32))
> +		return;
> +
> +	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
> +				RS690_LOWER_TOP_OF_DRAM2);
> +	pci_read_config_dword(pdev, RS690_HTIU_NB_DATA, &val);
> +
> +	if (val)
> +		return;
> +
> +	pci_info(pdev, "Adjusting top of DRAM to %pa for 64-bit DMA support\n", &top_of_dram);
> +
> +	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
> +		RS690_UPPER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
> +	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA, top_of_dram >> 32);
> +
> +	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
> +		RS690_LOWER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
> +	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA,
> +		top_of_dram | RS690_LOWER_TOP_OF_DRAM2_VALID);
> +}
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS690,
> +			rs690_fix_64bit_dma);
> +
>  #endif
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 4c3fa5293d76..0a7fe2ed520b 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -381,6 +381,7 @@
>  #define PCI_DEVICE_ID_ATI_RS400_166     0x5a32
>  #define PCI_DEVICE_ID_ATI_RS400_200     0x5a33
>  #define PCI_DEVICE_ID_ATI_RS480         0x5950
> +#define PCI_DEVICE_ID_ATI_RS690         0x7910
>  /* ATI IXP Chipset */
>  #define PCI_DEVICE_ID_ATI_IXP200_IDE	0x4349
>  #define PCI_DEVICE_ID_ATI_IXP200_SMBUS	0x4353
> -- 
> 2.13.7
> 

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

end of thread, other threads:[~2021-06-16 23:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-27 21:45 [PATCH] PCI: Add quirk for 64-bit DMA on RS690 chipset Mikel Rychliski
2021-06-04 23:02 ` Bjorn Helgaas
2021-06-07  4:37   ` Mikel Rychliski
2021-06-11 21:48     ` [PATCH v2] " Mikel Rychliski
2021-06-16 23:23       ` Bjorn Helgaas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.