lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20080629144615.GJ1540@electric-eye.fr.zoreil.com>
Date:	Sun, 29 Jun 2008 16:46:15 +0200
From:	Francois Romieu <romieu@...zoreil.com>
To:	netdev@...r.kernel.org
Cc:	jeff@...zik.org, akpm@...ux-foundation.org,
	Edward Hsu <edward_hsu@...ltek.com.tw>,
	Mario Limonciello <mario_limonciello@...l.com>,
	Kasper Sandberg <lkml@...anurb.dk>
Subject: [PATCH 9/13] r8169: sync existing 8168 device hardware start
	sequences with vendor driver

This part of the driver should be reasonably in line with Realtek's
8.006.00 driver.

I have left some bits related to jumbo frame and optional features
aside for now.

Signed-off-by: Francois Romieu <romieu@...zoreil.com>
Cc: Edward Hsu <edward_hsu@...ltek.com.tw>
---
 drivers/net/r8169.c |  161 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 161 insertions(+), 0 deletions(-)

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 46bdcb9..d8296fc 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -527,6 +527,72 @@ static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value)
 	mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value);
 }
 
+static void rtl8168_ephy_write(void __iomem *ioaddr, int reg_addr, int value)
+{
+	unsigned int i;
+
+	RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
+		(reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
+
+	for (i = 0; i < 100; i++) {
+		if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG))
+			break;
+		udelay(10);
+	}
+}
+
+static u16 rtl8168_ephy_read(void __iomem *ioaddr, int reg_addr)
+{
+	u16 value = 0xffff;
+	unsigned int i;
+
+	RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
+
+	for (i = 0; i < 100; i++) {
+		if (RTL_R32(EPHYAR) & EPHYAR_FLAG) {
+			value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK;
+			break;
+		}
+		udelay(10);
+	}
+
+	return value;
+}
+
+static void rtl8168_csi_write(void __iomem *ioaddr, int addr, int value)
+{
+	unsigned int i;
+
+	RTL_W32(CSIDR, value);
+	RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
+		CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
+
+	for (i = 0; i < 100; i++) {
+		if (!(RTL_R32(CSIAR) & CSIAR_FLAG))
+			break;
+		udelay(10);
+	}
+}
+
+static u32 rtl8168_csi_read(void __iomem *ioaddr, int addr)
+{
+	u32 value = ~0x00;
+	unsigned int i;
+
+	RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
+		CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
+
+	for (i = 0; i < 100; i++) {
+		if (RTL_R32(CSIAR) & CSIAR_FLAG) {
+			value = RTL_R32(CSIDR);
+			break;
+		}
+		udelay(10);
+	}
+
+	return value;
+}
+
 static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
 {
 	RTL_W16(IntrMask, 0x0000);
@@ -2166,33 +2232,128 @@ static void rtl8168_tx_performance_tweak(struct pci_dev *pdev,
 	pci_write_config_byte(pdev, reg, ctl);
 }
 
+static void rtl8168_disable_clock_request(struct pci_dev *pdev)
+{
+	pci_write_config_byte(pdev, 0x81, 0x00);
+}
+
+/*
+ * Taken from Realtek's 8168 driver.
+ *
+ * There is not much description for these bits in the datasheet.
+ * Note that Mac_dbgo_sel forces the PCI DAC bit to zero. Tnis should
+ * be taken into consideration to implement proper DAC support on
+ * the 8168 family. -- FR
+ */
+static void rtl8168c_cpcmd_quirk(void __iomem *ioaddr)
+{
+	RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~(EnableBist | Mac_dbgo_oe |
+		Force_half_dup | Force_rxflow_en | Force_txflow_en |
+		Cxpl_dbg_sel | ASF | PktCntrDisable | Mac_dbgo_sel));
+}
+
+static void rtl8168_csi_access_enable(void __iomem *ioaddr)
+{
+	u32 csi;
+
+	csi = rtl8168_csi_read(ioaddr, 0x070c) & 0x00ffffff;
+	rtl8168_csi_write(ioaddr, 0x070c, csi | 0x27000000);
+}
+
+struct ephy_info {
+	unsigned int offset;
+	u16 mask;
+	u16 bits;
+};
+
+static void rtl8168_ephy_init(void __iomem *ioaddr, struct ephy_info *e,
+			      int len)
+{
+	u16 w;
+
+	while (len-- > 0) {
+		w = (rtl8168_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits;
+		rtl8168_ephy_write(ioaddr, e->offset, w);
+		e++;
+	}
+}
+
 static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev)
 {
+	RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
+	rtl8168c_cpcmd_quirk(ioaddr);
+
 	rtl8168_tx_performance_tweak(pdev, 0x69, 0x58);
 }
 
 static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev)
 {
 	rtl_hw_start_8168bb(ioaddr, pdev);
+
+	RTL_W8(EarlyTxThres, EarlyTxThld);
+
+	RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
 }
 
 static void __rtl_hw_start_8168cpx(void __iomem *ioaddr, struct pci_dev *pdev)
 {
+	RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
+
+	RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
+
 	rtl8168_tx_performance_tweak(pdev, 0x79, 0x50);
+
+	rtl8168_disable_clock_request(pdev);
+
+	rtl8168c_cpcmd_quirk(ioaddr);
 }
 
 static void rtl_hw_start_8168c(void __iomem *ioaddr, struct pci_dev *pdev)
 {
+	static struct ephy_info e_info_8168c[] = {
+		{ 0x02, 1 << 11,	1 << 12 },
+		{ 0x03, 0,		1 <<  1 },
+		{ 0x06, 1 <<  7,	0 }
+	};
+
+	rtl8168_csi_access_enable(ioaddr);
+
+	RTL_W8(DBG_REG, 0x0e | FIX_NAK_1 | FIX_NAK_2);
+
+	rtl8168_ephy_init(ioaddr, e_info_8168c, ARRAY_SIZE(e_info_8168c));
+
 	__rtl_hw_start_8168cpx(ioaddr, pdev);
 }
 
 static void rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev)
 {
+	static struct ephy_info e_info_8168cp[] = {
+		{ 0x01, 0,		1 <<  0 },
+		{ 0x02, 1 << 11,	1 << 12 },
+		{ 0x03, 0,		1 <<  6 | 1 << 1 },
+		{ 0x06, (1 <<  7),	0 },
+		{ 0x07, 0,		1 << 13 }
+	};
+
+	rtl8168_csi_access_enable(ioaddr);
+
+	rtl8168_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
+
 	__rtl_hw_start_8168cpx(ioaddr, pdev);
 }
 
 static void rtl_hw_start_8168cx(void __iomem *ioaddr, struct pci_dev *pdev)
 {
+	static struct ephy_info e_info_8168cx[] = {
+		{ 0x01, 0,		1 <<  0 },
+		{ 0x03, 1 << 10,	1 <<  9 | 1 << 5 }
+	};
+
+	rtl8168_csi_access_enable(ioaddr);
+
+	rtl8168_ephy_init(ioaddr, e_info_8168cx, ARRAY_SIZE(e_info_8168cx));
+
 	__rtl_hw_start_8168cpx(ioaddr, pdev);
 }
 
-- 
1.5.3.3

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ