Skip to content

Commit

Permalink
firmware: convert acenic driver to request_firmware()
Browse files Browse the repository at this point in the history
We store the firmware in its native big-endian form now, so the loop in
ace_copy() is modified to use be32_to_cpup() when writing it out.

We can forget the BSS,SBSS sections of the firmware, since we were
clearing all the device's RAM anyway. And the text,rodata,data sections
can all be loaded as a single chunk since they're contiguous (give or
take a few dozen bytes in between).

Signed-off-by: Jaswinder Singh <[email protected]>
Signed-off-by: David Woodhouse <[email protected]>
Acked-by: Jes Sorensen <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Jaswinder Singh authored and davem330 committed Jan 5, 2009
1 parent 14deae4 commit 949b425
Show file tree
Hide file tree
Showing 6 changed files with 9,510 additions and 46 deletions.
117 changes: 71 additions & 46 deletions drivers/net/acenic.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/sockios.h>
#include <linux/firmware.h>

#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#include <linux/if_vlan.h>
Expand Down Expand Up @@ -186,8 +187,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
Expand Down Expand Up @@ -417,6 +416,10 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
MODULE_AUTHOR("Jes Sorensen <[email protected]>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
#ifndef CONFIG_ACENIC_OMIT_TIGON_I
MODULE_FIRMWARE("acenic/tg1.bin");
#endif
MODULE_FIRMWARE("acenic/tg2.bin");

module_param_array_named(link, link_state, int, NULL, 0);
module_param_array(trace, int, NULL, 0);
Expand Down Expand Up @@ -943,17 +946,17 @@ 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, &regs->LocalCtrl);
ap->version = 1;
ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES;
break;
#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(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
readl(&regs->CpuBCtrl); /* PCI write posting */
/*
Expand Down Expand Up @@ -1205,7 +1208,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;
Expand Down Expand Up @@ -1441,10 +1446,7 @@ static int __devinit ace_init(struct net_device *dev)
if (ap->version >= 2)
writel(tmp, &regs->TuneFastLink);

if (ACE_IS_TIGON_I(ap))
writel(tigonFwStartAddr, &regs->Pc);
if (ap->version == 2)
writel(tigon2FwStartAddr, &regs->Pc);
writel(ap->firmware_start, &regs->Pc);

writel(0, &regs->Mb0Lo);

Expand Down Expand Up @@ -2761,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),
Expand Down Expand Up @@ -2869,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 __be32 *src,
u32 dest, int size)
{
void __iomem *tdest;
u32 *wsrc;
short tsize, i;

if (size <= 0)
Expand All @@ -2885,20 +2886,15 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
tdest = (void __iomem *) &regs->Window +
(dest & (ACE_WINDOW_SIZE - 1));
writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->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 big-endian */
writel(be32_to_cpup(src), tdest);
src++;
tdest += 4;
dest += 4;
size -= 4;
}
dest += tsize;
src += tsize;
size -= tsize;
}

return;
}


Expand Down Expand Up @@ -2937,37 +2933,66 @@ 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 __be32 *fw_data;
u32 load_addr;
int ret;

if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
printk(KERN_ERR "%s: trying to download firmware while the "
"CPU is running!\n", ap->name);
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 = be32_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 = be32_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;
}


Expand Down
4 changes: 4 additions & 0 deletions drivers/net/acenic.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,10 @@ struct ace_private
u32 last_tx, last_std_rx, last_mini_rx;
#endif
int pci_using_dac;
u8 firmware_major;
u8 firmware_minor;
u8 firmware_fix;
u32 firmware_start;
};


Expand Down
7 changes: 7 additions & 0 deletions firmware/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ fw-external-y := $(subst ",,$(CONFIG_EXTRA_FIRMWARE))
# accurate. In the latter case it doesn't matter -- it'll use $(fw-shipped-all).
# But be aware that the config file might not be included at all.

ifdef CONFIG_ACENIC_OMIT_TIGON_I
acenic-objs := acenic/tg2.bin
fw-shipped- += acenic/tg1.bin
else
acenic-objs := acenic/tg1.bin acenic/tg2.bin
endif
fw-shipped-$(CONFIG_ACENIC) += $(acenic-objs)
fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin
fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw
fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin
Expand Down
11 changes: 11 additions & 0 deletions firmware/WHENCE
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,14 @@ License: GPLv2 or OpenIB.org BSD license, no source visible

--------------------------------------------------------------------------

Driver: acenic -- Alteon AceNIC Gigabit Ethernet card

File: acenic/tg1.bin
File: acenic/tg2.bin

Licence: Unknown

Found in hex form in kernel source, but source allegedly available at
http://alteon.shareable.org/

--------------------------------------------------------------------------
Loading

0 comments on commit 949b425

Please sign in to comment.