Skip to content

Commit

Permalink
netxen: fix firmware download
Browse files Browse the repository at this point in the history
o hold the firmware in memory across suspend, since filesystem
  may not be up after resuming.
o reset the chip after requesting firmware, to minimize downtime
  for NC-SI.

Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Dhananjay Phadke authored and David S. Miller committed Apr 29, 2009
1 parent 4ea528a commit f7185c7
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 207 deletions.
9 changes: 7 additions & 2 deletions drivers/net/netxen/netxen_nic.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <linux/in.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/firmware.h>

#include <linux/ethtool.h>
#include <linux/mii.h>
Expand Down Expand Up @@ -1255,8 +1256,6 @@ struct netxen_adapter {
u32 flags;
u32 irq;
u32 temp;
u32 fw_major;
u32 fw_version;

struct netxen_adapter_stats stats;

Expand Down Expand Up @@ -1295,6 +1294,10 @@ struct netxen_adapter {
struct net_device_stats net_stats;

nx_nic_intr_coalesce_t coal;

u32 fw_major;
u32 fw_version;
const struct firmware *fw;
};

/*
Expand Down Expand Up @@ -1376,6 +1379,8 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter);
int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
int netxen_load_firmware(struct netxen_adapter *adapter);
void netxen_request_firmware(struct netxen_adapter *adapter);
void netxen_release_firmware(struct netxen_adapter *adapter);
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);

int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
Expand Down
195 changes: 0 additions & 195 deletions drivers/net/netxen/netxen_nic_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include "netxen_nic_hw.h"
#include "netxen_nic_phan_reg.h"

#include <linux/firmware.h>
#include <net/ip.h>

#define MASK(n) ((1ULL<<(n))-1)
Expand Down Expand Up @@ -1016,200 +1015,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off)
(ulong)adapter->ahw.pci_base0;
}

static int
netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname,
const struct firmware *fw)
{
u64 *ptr64;
u32 i, flashaddr, size;
struct pci_dev *pdev = adapter->pdev;

if (fw)
dev_info(&pdev->dev, "loading firmware from file %s\n", fwname);
else
dev_info(&pdev->dev, "loading firmware from flash\n");

if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1);

if (fw) {
__le64 data;

size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8;

ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START];
flashaddr = NETXEN_BOOTLD_START;

for (i = 0; i < size; i++) {
data = cpu_to_le64(ptr64[i]);
adapter->pci_mem_write(adapter, flashaddr, &data, 8);
flashaddr += 8;
}

size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET];
size = (__force u32)cpu_to_le32(size) / 8;

ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START];
flashaddr = NETXEN_IMAGE_START;

for (i = 0; i < size; i++) {
data = cpu_to_le64(ptr64[i]);

if (adapter->pci_mem_write(adapter,
flashaddr, &data, 8))
return -EIO;

flashaddr += 8;
}
} else {
u32 data;

size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4;
flashaddr = NETXEN_BOOTLD_START;

for (i = 0; i < size; i++) {
if (netxen_rom_fast_read(adapter,
flashaddr, (int *)&data) != 0)
return -EIO;

if (adapter->pci_mem_write(adapter,
flashaddr, &data, 4))
return -EIO;

flashaddr += 4;
}
}
msleep(1);

if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
else {
NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0);
}

return 0;
}

static int
netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname,
const struct firmware *fw)
{
__le32 val;
u32 major, minor, build, ver, min_ver, bios;
struct pci_dev *pdev = adapter->pdev;

if (fw->size < NX_FW_MIN_SIZE)
return -EINVAL;

val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
if ((__force u32)val != NETXEN_BDINFO_MAGIC)
return -EINVAL;

val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
major = (__force u32)val & 0xff;
minor = ((__force u32)val >> 8) & 0xff;
build = (__force u32)val >> 16;

if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
min_ver = NETXEN_VERSION_CODE(4, 0, 216);
else
min_ver = NETXEN_VERSION_CODE(3, 4, 216);

ver = NETXEN_VERSION_CODE(major, minor, build);

if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
dev_err(&pdev->dev,
"%s: firmware version %d.%d.%d unsupported\n",
fwname, major, minor, build);
return -EINVAL;
}

val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
if ((__force u32)val != bios) {
dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
fwname);
return -EINVAL;
}

/* check if flashed firmware is newer */
if (netxen_rom_fast_read(adapter,
NX_FW_VERSION_OFFSET, (int *)&val))
return -EIO;
major = (__force u32)val & 0xff;
minor = ((__force u32)val >> 8) & 0xff;
build = (__force u32)val >> 16;
if (NETXEN_VERSION_CODE(major, minor, build) > ver)
return -EINVAL;

NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
return 0;
}

static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" };

int netxen_load_firmware(struct netxen_adapter *adapter)
{
u32 capability, flashed_ver;
const struct firmware *fw;
int fw_type;
struct pci_dev *pdev = adapter->pdev;
int rc = 0;

if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
fw_type = NX_P2_MN_ROMIMAGE;
goto request_fw;
} else {
fw_type = NX_P3_CT_ROMIMAGE;
goto request_fw;
}

request_mn:
capability = 0;

netxen_rom_fast_read(adapter,
NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY);
if (capability & NX_PEG_TUNE_MN_PRESENT) {
fw_type = NX_P3_MN_ROMIMAGE;
goto request_fw;
}
}

request_fw:
rc = request_firmware(&fw, fw_name[fw_type], &pdev->dev);
if (rc != 0) {
if (fw_type == NX_P3_CT_ROMIMAGE) {
msleep(1);
goto request_mn;
}

fw = NULL;
goto load_fw;
}

rc = netxen_validate_firmware(adapter, fw_name[fw_type], fw);
if (rc != 0) {
release_firmware(fw);

if (fw_type == NX_P3_CT_ROMIMAGE) {
msleep(1);
goto request_mn;
}

fw = NULL;
}

load_fw:
rc = netxen_do_load_firmware(adapter, fw_name[fw_type], fw);

if (fw)
release_firmware(fw);
return rc;
}

int
netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data)
{
Expand Down
Loading

0 comments on commit f7185c7

Please sign in to comment.