From 3306f1917d45bf194cbaefa2349e66289d0686c2 Mon Sep 17 00:00:00 2001 From: Maximilian Attems Date: Mon, 16 Jun 2008 11:28:20 +0000 Subject: [PATCH] add acenic request_firmware patch hmm nr of disabled drivers goes down, thanks to upstream effort. svn path=/dists/trunk/linux-2.6/; revision=11643 --- debian/changelog | 1 + .../drivers-net-acenic-firmwar_request.patch | 296 ++++++++++++++++++ debian/patches/series/1~experimental.1 | 1 + 3 files changed, 298 insertions(+) create mode 100644 debian/patches/features/all/drivers-net-acenic-firmwar_request.patch diff --git a/debian/changelog b/debian/changelog index b2c9af3e2..cfcf742f7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -40,6 +40,7 @@ linux-2.6 (2.6.26~rc6-1~experimental.1) UNRELEASED; urgency=low * 486: enable OLPC support thanks Andres Salomon for merge. Kconfig variable patch by Robert Millan (closes: #485063). * Add request_firmware patch for ip2. + * Add request_firmware patch for acenic. (closes: #284221) [ Martin Michlmayr ] * [arm/orion5x] Update the config to reflect upstream renaming this diff --git a/debian/patches/features/all/drivers-net-acenic-firmwar_request.patch b/debian/patches/features/all/drivers-net-acenic-firmwar_request.patch new file mode 100644 index 000000000..df3623d3a --- /dev/null +++ b/debian/patches/features/all/drivers-net-acenic-firmwar_request.patch @@ -0,0 +1,296 @@ +Subject: [PATCH] firmware: convert acenic driver to request_firmware() +From: David Woodhouse +To: Jes Sorensen +Cc: netdev@vger.kernel.org, jaswinder@infradead.org + +Again with help from Jaswinder Singh. + +Omitting the large part of the patch which actually moves the firmware +around, since you'll need to pull from the git tree to get the preceding +patches if you want to test it anyway. + +We store the firmware in little-endian form now, and thus use +__raw_writel() to write it to the device, to avoid byteswapping by +writel(). I've revamped that loop in ace_copy() a little bit so it could +probably do with being tested. + +I've dropped the information about SBSS and BSS sections of the firmware +-- we were clearing the whole of the device's memory in advance anyway, +so clearing the BSS sections for a _second_ time seems pointless. And +since the text,rodata,data sections were (almost) contiguous, we now +just load those as a single blob rather than keeping them separate. + +Although it probably isn't necessary, we do preserve the ability to +change the load and start addresses from 0x4000, by putting them into a +header at the beginning of the firmware blob, along with the version +number. + +[ ported to debian -maks ] + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index f80c839..7677680 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -1912,8 +1912,8 @@ if NETDEV_1000 + + config ACENIC + tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support" +- depends on BROKEN + depends on PCI ++ select FW_LOADER + ---help--- + Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear + GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet +@@ -1945,6 +1946,23 @@ config ACENIC_OMIT_TIGON_I + + The safe and default value for this is N. + ++config ACENIC_TG1_FIRMWARE ++ bool "Include firmware for old Tigon I based AceNICs" ++ depends on ACENIC && !ACENIC_OMIT_TIGON_I ++ ---help--- ++ This includes firmware for the original Alteon AceNIC and 3Com 3C985 ++ (non B version) in the kernel image. ++ Say 'N' and let it get loaded from userspace on demand ++ ++config ACENIC_TG2_FIRMWARE ++ bool "Include firmware for Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit" ++ depends on ACENIC ++ ---help--- ++ This includes firmware for later Alteon AceNIC, 3Com 3C985B, ++ NetGear GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit ++ Ethernet adapter. ++ Say 'N' and let it get loaded from userspace on demand ++ + config DL2K + tristate "DL2000/TC902x-based Gigabit Ethernet support" + depends on PCI +diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c +index 6c19265..1e42734 100644 +--- a/drivers/net/acenic.c ++++ b/drivers/net/acenic.c +@@ -67,6 +67,7 @@ + #include + #include + #include ++#include + + #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + #include +@@ -187,8 +188,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); + #define MAX_RODATA_LEN 8*1024 + #define MAX_DATA_LEN 2*1024 + +-#include "acenic_firmware.h" +- + #ifndef tigon2FwReleaseLocal + #define tigon2FwReleaseLocal 0 + #endif +@@ -418,6 +417,8 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; + MODULE_AUTHOR("Jes Sorensen "); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); ++MODULE_FIRMWARE("acenic_tg1.bin"); ++MODULE_FIRMWARE("acenic_tg2.bin"); + + module_param_array_named(link, link_state, int, NULL, 0); + module_param_array(trace, int, NULL, 0); +@@ -939,8 +940,8 @@ static int __devinit ace_init(struct net_device *dev) + case 4: + case 5: + printk(KERN_INFO " Tigon I (Rev. %i), Firmware: %i.%i.%i, ", +- tig_ver, tigonFwReleaseMajor, tigonFwReleaseMinor, +- tigonFwReleaseFix); ++ tig_ver, ap->firmware_major, ap->firmware_minor, ++ ap->firmware_fix); + writel(0, ®s->LocalCtrl); + ap->version = 1; + ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES; +@@ -948,8 +949,8 @@ static int __devinit ace_init(struct net_device *dev) + #endif + case 6: + printk(KERN_INFO " Tigon II (Rev. %i), Firmware: %i.%i.%i, ", +- tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor, +- tigon2FwReleaseFix); ++ tig_ver, ap->firmware_major, ap->firmware_minor, ++ ap->firmware_fix); + writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); + readl(®s->CpuBCtrl); /* PCI write posting */ + /* +@@ -1201,7 +1202,9 @@ static int __devinit ace_init(struct net_device *dev) + memset(ap->info, 0, sizeof(struct ace_info)); + memset(ap->skb, 0, sizeof(struct ace_skb)); + +- ace_load_firmware(dev); ++ if (ace_load_firmware(dev)) ++ goto init_error; ++ + ap->fw_running = 0; + + tmp_ptr = ap->info_dma; +@@ -1437,10 +1440,7 @@ static int __devinit ace_init(struct net_device *dev) + if (ap->version >= 2) + writel(tmp, ®s->TuneFastLink); + +- if (ACE_IS_TIGON_I(ap)) +- writel(tigonFwStartAddr, ®s->Pc); +- if (ap->version == 2) +- writel(tigon2FwStartAddr, ®s->Pc); ++ writel(ap->firmware_start, ®s->Pc); + + writel(0, ®s->Mb0Lo); + +@@ -2763,8 +2763,8 @@ static void ace_get_drvinfo(struct net_device *dev, + + strlcpy(info->driver, "acenic", sizeof(info->driver)); + snprintf(info->version, sizeof(info->version), "%i.%i.%i", +- tigonFwReleaseMajor, tigonFwReleaseMinor, +- tigonFwReleaseFix); ++ ap->firmware_major, ap->firmware_minor, ++ ap->firmware_fix); + + if (ap->pdev) + strlcpy(info->bus_info, pci_name(ap->pdev), +@@ -2871,11 +2871,10 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev) + } + + +-static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src, +- u32 dest, int size) ++static void __devinit ace_copy(struct ace_regs __iomem *regs, const __le32 *src, ++ u32 dest, int size) + { + void __iomem *tdest; +- u32 *wsrc; + short tsize, i; + + if (size <= 0) +@@ -2887,20 +2886,15 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src, + tdest = (void __iomem *) ®s->Window + + (dest & (ACE_WINDOW_SIZE - 1)); + writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); +- /* +- * This requires byte swapping on big endian, however +- * writel does that for us +- */ +- wsrc = src; + for (i = 0; i < (tsize / 4); i++) { +- writel(wsrc[i], tdest + i*4); ++ /* Firmware is stored as little-endian */ ++ __raw_writel(*src, tdest); ++ src++; ++ tdest += 4; ++ dest += 4; ++ size -= 4; + } +- dest += tsize; +- src += tsize; +- size -= tsize; + } +- +- return; + } + + +@@ -2939,8 +2933,13 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz + */ + static int __devinit ace_load_firmware(struct net_device *dev) + { ++ const struct firmware *fw; ++ const char *fw_name = "acenic_tg2.bin"; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; ++ const __le32 *fw_data; ++ u32 load_addr; ++ int ret; + + if (!(readl(®s->CpuCtrl) & CPU_HALTED)) { + printk(KERN_ERR "%s: trying to download firmware while the " +@@ -2948,28 +2947,52 @@ static int __devinit ace_load_firmware(struct net_device *dev) + return -EFAULT; + } + ++ if (ACE_IS_TIGON_I(ap)) ++ fw_name = "acenic_tg1.bin"; ++ ++ ret = request_firmware(&fw, fw_name, &ap->pdev->dev); ++ if (ret) { ++ printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", ++ ap->name, fw_name); ++ return ret; ++ } ++ ++ fw_data = (void *)fw->data; ++ ++ /* Firmware blob starts with version numbers, followed by ++ load and start address. Remainder is the blob to be loaded ++ contiguously from load address. We don't bother to represent ++ the BSS/SBSS sections any more, since we were clearing the ++ whole thing anyway. */ ++ ap->firmware_major = fw->data[0]; ++ ap->firmware_minor = fw->data[1]; ++ ap->firmware_fix = fw->data[2]; ++ ++ ap->firmware_start = le32_to_cpu(fw_data[1]); ++ if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) { ++ printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n", ++ ap->name, ap->firmware_start, fw_name); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ load_addr = le32_to_cpu(fw_data[2]); ++ if (load_addr < 0x4000 || load_addr >= 0x80000) { ++ printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n", ++ ap->name, load_addr, fw_name); ++ ret = -EINVAL; ++ goto out; ++ } ++ + /* +- * Do not try to clear more than 512KB or we end up seeing +- * funny things on NICs with only 512KB SRAM ++ * Do not try to clear more than 512KiB or we end up seeing ++ * funny things on NICs with only 512KiB SRAM + */ + ace_clear(regs, 0x2000, 0x80000-0x2000); +- if (ACE_IS_TIGON_I(ap)) { +- ace_copy(regs, tigonFwText, tigonFwTextAddr, tigonFwTextLen); +- ace_copy(regs, tigonFwData, tigonFwDataAddr, tigonFwDataLen); +- ace_copy(regs, tigonFwRodata, tigonFwRodataAddr, +- tigonFwRodataLen); +- ace_clear(regs, tigonFwBssAddr, tigonFwBssLen); +- ace_clear(regs, tigonFwSbssAddr, tigonFwSbssLen); +- }else if (ap->version == 2) { +- ace_clear(regs, tigon2FwBssAddr, tigon2FwBssLen); +- ace_clear(regs, tigon2FwSbssAddr, tigon2FwSbssLen); +- ace_copy(regs, tigon2FwText, tigon2FwTextAddr,tigon2FwTextLen); +- ace_copy(regs, tigon2FwRodata, tigon2FwRodataAddr, +- tigon2FwRodataLen); +- ace_copy(regs, tigon2FwData, tigon2FwDataAddr,tigon2FwDataLen); +- } +- +- return 0; ++ ace_copy(regs, &fw_data[3], load_addr, fw->size-12); ++ out: ++ release_firmware(fw); ++ return ret; + } + + +diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h +index 60ed183..cf7e80e 100644 +--- a/drivers/net/acenic.h ++++ b/drivers/net/acenic.h +@@ -695,6 +695,10 @@ struct ace_private + #endif + struct net_device_stats stats; + int pci_using_dac; ++ u8 firmware_major; ++ u8 firmware_minor; ++ u8 firmware_fix; ++ u32 firmware_start; + }; + + + diff --git a/debian/patches/series/1~experimental.1 b/debian/patches/series/1~experimental.1 index 1115022d0..52ee86186 100644 --- a/debian/patches/series/1~experimental.1 +++ b/debian/patches/series/1~experimental.1 @@ -11,6 +11,7 @@ #+ debian/dfsg/drivers-net-bnx2-request_firmware-1.patch + features/all/drivers-usb-serial-keyspan-request_firmware.patch + features/all/drivers-char-ip2-request_firmware.patch ++ features/all/drivers-net-acenic-firmwar_request.patch + features/all/export-gfs2-locking-symbols.patch + features/all/export-unionfs-symbols.patch