Skip to contentSkip to conversation

r8169: fix invalid register dump

PATCH Superseded Peter Wu 3 participants 3 messages Aug 17, 2013

Subsystems (3)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore

Peter Wu

author
#0 lore raw

PATCH v2 1/1 r8169: fix invalid register dump

From: Peter Wu <[email protected]>

For some reason, my PCIe RTL8111E onboard NIC on a GA-Z68X-UD3H-B3 motherboard reads as FFs when reading from MMIO with a block size larger than 7. Therefore change to reading blocks of four bytes.

Thanks to Francois for a better implementation.

---
 drivers/net/ethernet/realtek/r8169.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/ethernet/realtek/r8169.c +5 -1
index b5eb419..2943916 100644
@@ -1897,12 +1897,16 @@ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 			     void *p)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
+	u32 __iomem *data = tp->mmio_addr;
+	u32 *dw = p;
+	int i;
 
 	if (regs->len > R8169_REGS_SIZE)
 		regs->len = R8169_REGS_SIZE;
 
 	rtl_lock_work(tp);
-	memcpy_fromio(p, tp->mmio_addr, regs->len);
+	for (i = regs->len; i > 0; i -= 4)
+		memcpy_fromio(dw++, data++, min(4, i));
 	rtl_unlock_work(tp);
 }
 
Signature · 1 line
1.8.3.4
#1 lore raw
Quoted 22 lines · Peter Wu

From: Peter Wu <[email protected]>

For some reason, my PCIe RTL8111E onboard NIC on a GA-Z68X-UD3H-B3 motherboard reads as FFs when reading from MMIO with a block size larger than 7. Therefore change to reading blocks of four bytes.

Thanks to Francois for a better implementation.

---
 drivers/net/ethernet/realtek/r8169.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/ethernet/realtek/r8169.c +1 -0
index b5eb419..2943916 100644
@@ -1897,12 +1897,16 @@ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 			     void *p)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
+	u32 __iomem *data = tp->mmio_addr;

drivers/net/ethernet/realtek/r8169.c static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, · line 1909

Quoted 10 lines
drivers/net/ethernet/realtek/r8169.c +4 -1
+	u32 *dw = p;
+	int i;
 
 	if (regs->len > R8169_REGS_SIZE)
 		regs->len = R8169_REGS_SIZE;
 
 	rtl_lock_work(tp);
-	memcpy_fromio(p, tp->mmio_addr, regs->len);
+	for (i = regs->len; i > 0; i -= 4)
+		memcpy_fromio(dw++, data++, min(4, i));

I would be very wary of accessing registers with any width other than the usual (32 bits).

And as I said, the kernel buffer is always large enough for all your registers, so this could just be:

	for (i = 0; i < R8169_REGS_SIZE; i += 4)
		memcpy_fromio(dw++, data++, 4);

Ben.

Quoted 3 lines
drivers/net/ethernet/realtek/r8169.c +0 -0
 	rtl_unlock_work(tp);
 }
 
Signature · 3 lines
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
#2 lore raw

Ben Hutchings <[email protected]> :
[...]

Quoted 2 lines

I would be very wary of accessing registers with any width other than the usual (32 bits).

You are right. Most registers do not seem to care - some are 8 bits wide - but the 8168c datasheet states that it's out of spec for the descriptor ring address registers.

Peter, please use Ben's suggestion as is.

Signature · 1 line
Ueimor