r8169: Allow RTL8168D v1 and v2 to be used without firmware files (Closes: #561309)

svn path=/dists/trunk/linux-2.6/; revision=14803
This commit is contained in:
Ben Hutchings 2009-12-21 01:37:24 +00:00
parent b7bad86edf
commit d9cddba68f
3 changed files with 140 additions and 0 deletions

2
debian/changelog vendored
View File

@ -16,6 +16,8 @@ linux-2.6 (2.6.32-3) UNRELEASED; urgency=high
- hfs: fix a potential buffer overflow (CVE-2009-4020)
* ia64: Include <linux/personality.h> header in <asm/fcntl.h>; fixes
FTBFS
* r8169: Allow RTL8168D v1 and v2 to be used without firmware files
(Closes: #561309)
-- Martin Michlmayr <tbm@cyrius.com> Fri, 18 Dec 2009 15:34:01 +0000

View File

@ -0,0 +1,135 @@
From: Ben Hutchings <ben@decadent.org.uk>
Subject: [PATCH] r8169: remove firmware for RTL8169D PHY
The recently added support for RTL8169D chips included some machine
code without accompanying source code. Replace this with use of the
firmware loader.
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2170,6 +2170,7 @@ config R8169
depends on PCI
select CRC32
select MII
+ select FW_LOADER
---help---
Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -23,6 +23,7 @@
#include <linux/tcp.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -1359,6 +1360,23 @@ static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len)
}
}
+struct phy_reg_le {
+ __le16 reg;
+ __le16 val;
+};
+
+static void rtl_phy_write_fw(void __iomem *ioaddr, const struct firmware *fw)
+{
+ const struct phy_reg_le *regs = (const struct phy_reg_le *)fw->data;
+ size_t len = fw->size / sizeof(*regs);
+
+ while (len-- > 0) {
+ mdio_write(ioaddr, le16_to_cpu(regs->reg),
+ le16_to_cpu(regs->val));
+ regs++;
+ }
+}
+
static void rtl8169s_hw_phy_config(void __iomem *ioaddr)
{
struct phy_reg phy_reg_init[] = {
@@ -1691,7 +1709,7 @@ static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr)
rtl8168c_3_hw_phy_config(ioaddr);
}
-static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
{
static struct phy_reg phy_reg_init_0[] = {
{ 0x1f, 0x0001 },
@@ -1719,6 +1737,8 @@ static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
{ 0x05, 0x8332 },
{ 0x06, 0x5561 }
};
+ void __iomem *ioaddr = tp->mmio_addr;
+ const struct firmware *fw;
rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
@@ -1776,12 +1801,18 @@ static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600);
mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000);
-#ifdef CONFIG_BROKEN
- rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2));
-#endif
+ if (request_firmware(&fw, "rtl8168d-1.fw", &tp->pci_dev->dev) == 0) {
+ rtl_phy_write_fw(ioaddr, fw);
+ release_firmware(fw);
+ } else {
+ printk(KERN_WARNING "%s: unable to apply firmware patch\n",
+ tp->dev->name);
+ }
}
-static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr)
+MODULE_FIRMWARE("rtl8168d-1.fw");
+
+static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
{
static struct phy_reg phy_reg_init_0[] = {
{ 0x1f, 0x0001 },
@@ -1808,6 +1836,8 @@ static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr)
{ 0x05, 0x8332 },
{ 0x06, 0x5561 }
};
+ void __iomem *ioaddr = tp->mmio_addr;
+ const struct firmware *fw;
rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
@@ -1861,11 +1896,17 @@ static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr)
mdio_write(ioaddr, 0x1f, 0x0002);
mdio_patch(ioaddr, 0x0f, 0x0017);
-#ifdef CONFIG_BROKEN
- rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1));
-#endif
+ if (request_firmware(&fw, "rtl8168d-2.fw", &tp->pci_dev->dev) == 0) {
+ rtl_phy_write_fw(ioaddr, fw);
+ release_firmware(fw);
+ } else {
+ printk(KERN_WARNING "%s: unable to apply firmware patch\n",
+ tp->dev->name);
+ }
}
+MODULE_FIRMWARE("rtl8168d-2.fw");
+
static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr)
{
struct phy_reg phy_reg_init[] = {
@@ -2001,10 +2039,10 @@ static int rtl_hw_phy_config(struct net_device *dev)
rtl8168cp_2_hw_phy_config(ioaddr);
break;
case RTL_GIGA_MAC_VER_25:
- rtl8168d_1_hw_phy_config(ioaddr);
+ rtl8168d_1_hw_phy_config(tp);
break;
case RTL_GIGA_MAC_VER_26:
- rtl8168d_2_hw_phy_config(ioaddr);
+ rtl8168d_2_hw_phy_config(tp);
break;
case RTL_GIGA_MAC_VER_27:
rtl8168d_3_hw_phy_config(ioaddr);

View File

@ -7,3 +7,6 @@
- bugfix/mips/drm-ttm-build-fix.patch
+ bugfix/all/stable/2.6.32.2.patch
+ bugfix/ia64/ia64-Include-linux-personality.h-header-in-asm-fcntl.patch
- features/all/r8169-rtl8168d-1-2-request_firmware.patch
- features/all/r8169-init-phy-return-error.patch
+ features/all/r8169-rtl8168d-1-2-request_firmware-2.patch