[PATCH] r8169: inform about CLKRUN protocol issue when behind a CardBus bridge
From: Maciej S. Szmigiero
Date: Thu Sep 06 2018 - 12:11:06 EST
It turns out that at least some r8169 CardBus cards don't operate correctly
when CLKRUN protocol is enabled - the symptoms are recurring timeouts
during PHY reads / writes and a very high packet drop rate.
This is true of at least RTL8169sc/8110sc (XID 18000000) chip in
Sunrich C-160 CardBus NIC.
Such behavior was observed on two separate laptops, the first one has
TI PCIxx12 CardBus bridge, while the second one has Ricoh RL5c476II.
Setting CLKRUN_En bit in CONFIG 3 register via an EEPROM write didn't
improve things in either case (this is probably why it wasn't set by the
card manufacturer).
The only way to fix the issue was to disable the CLKRUN protocol either
in the CardBus bridge (only possible in the TI one) or in the southbridge.
Since the problem takes some time to debug let's warn people that have
the suspect configuration (Conventional PCI r8169 NIC behind a CardBus
bridge) so they know what they can do if they encounter it.
Signed-off-by: Maciej S. Szmigiero <mail@xxxxxxxxxxxxxxxxxxxxx>
---
drivers/net/ethernet/realtek/r8169.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index b08d51bf7a20..b935a18358cb 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -7254,6 +7254,22 @@ static int rtl_jumbo_max(struct rtl8169_private *tp)
}
}
+static void rtl_pci_cardbus_check(struct pci_dev *pdev)
+{
+ struct pci_dev *parent = pdev;
+
+ while ((parent = pci_upstream_bridge(parent)) != NULL) {
+ if (parent->hdr_type != PCI_HEADER_TYPE_CARDBUS)
+ continue;
+
+ dev_info(&pdev->dev,
+ "device is behind a CardBus bridge\n");
+ dev_info(&pdev->dev,
+ "in case of erratic or no operation try disabling CLKRUN protocol in the CardBus bridge or in the southbridge\n");
+ break;
+ }
+}
+
static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
@@ -7305,8 +7321,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->mmio_addr = pcim_iomap_table(pdev)[region];
- if (!pci_is_pcie(pdev))
+ if (!pci_is_pcie(pdev)) {
dev_info(&pdev->dev, "not PCI Express\n");
+ rtl_pci_cardbus_check(pdev);
+ }
/* Identify chip attached to board */
rtl8169_get_mac_version(tp, cfg->default_ver);
--
2.17.0