Commit c22202fa authored by Ben Hutchings's avatar Ben Hutchings Committed by Greg Kroah-Hartman

Staging: rt{2860,2870}sta: Use request_firmware() to load firmware

When originally introduced into staging, these drivers had custom
firmware-loading code which checked a version number and CRC at the
end of each blob.  This reintroduces those checks, using crc-ccitt
instead of custom code.

The removed firmware will be added to the linux-firmware.git
repository.

Based on work by Darren Salt <linux@youmustbejoking.demon.co.uk>.
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
Tested-By: default avatarDarren Salt <linux@youmustbejoking.demon.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 8838d256
......@@ -3,6 +3,8 @@ config RT2860
depends on PCI && X86 && WLAN
select WIRELESS_EXT
select WEXT_PRIV
select CRC_CCITT
select FW_LOADER
---help---
This is an experimental driver for the Ralink 2860 and 3090
wireless chips.
This diff is collapsed.
This diff is collapsed.
......@@ -37,35 +37,38 @@
#include "../rt_config.h"
#if defined(RT2860) || defined(RT3090)
#include "firmware.h"
#include "../../rt3090/firmware.h"
#endif
#ifdef RT2870
#include "../../rt3070/firmware.h"
#include "firmware_3070.h"
#endif
#include <linux/bitrev.h>
#include <linux/crc-ccitt.h>
#include <linux/firmware.h>
#ifdef RTMP_MAC_USB
/* */
/* RT2870 Firmware Spec only used 1 oct for version expression */
/* */
#define FIRMWARE_MINOR_VERSION 7
#endif /* RTMP_MAC_USB // */
/* New 8k byte firmware size for RT3071/RT3072 */
#define FIRMWAREIMAGE_MAX_LENGTH 0x2000
#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(u8))
#define FIRMWARE_MAJOR_VERSION 0
#define FIRMWAREIMAGE_LENGTH 0x1000
#define FIRMWAREIMAGEV1_LENGTH 0x1000
#define FIRMWAREIMAGEV2_LENGTH 0x1000
#define FIRMWARE_2870_MIN_VERSION 12
#define FIRMWARE_2870_FILENAME "rt2870.bin"
MODULE_FIRMWARE(FIRMWARE_2870_FILENAME);
#ifdef RTMP_MAC_PCI
#define FIRMWARE_MINOR_VERSION 2
#endif /* RTMP_MAC_PCI // */
#define FIRMWARE_3070_MIN_VERSION 17
#define FIRMWARE_3070_FILENAME "rt3070.bin"
MODULE_FIRMWARE(FIRMWARE_3070_FILENAME);
#define FIRMWARE_3071_MIN_VERSION 17
#define FIRMWARE_3071_FILENAME "rt3071.bin" /* for RT3071/RT3072 */
MODULE_FIRMWARE(FIRMWARE_3071_FILENAME);
#else /* RTMP_MAC_PCI */
#define FIRMWAREIMAGE_LENGTH 0x2000
#define FIRMWARE_2860_MIN_VERSION 11
#define FIRMWARE_2860_FILENAME "rt2860.bin"
MODULE_FIRMWARE(FIRMWARE_2860_FILENAME);
#define FIRMWARE_3090_MIN_VERSION 19
#define FIRMWARE_3090_FILENAME "rt3090.bin" /* for RT3090/RT3390 */
MODULE_FIRMWARE(FIRMWARE_3090_FILENAME);
#endif
/*
========================================================================
......@@ -90,6 +93,78 @@ int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd)
return 0;
}
static const struct firmware *rtmp_get_firmware(struct rt_rtmp_adapter *adapter)
{
const char *name;
const struct firmware *fw = NULL;
u8 min_version;
struct device *dev;
int err;
if (adapter->firmware)
return adapter->firmware;
#ifdef RTMP_MAC_USB
if (IS_RT3071(adapter)) {
name = FIRMWARE_3071_FILENAME;
min_version = FIRMWARE_3071_MIN_VERSION;
} else if (IS_RT3070(adapter)) {
name = FIRMWARE_3070_FILENAME;
min_version = FIRMWARE_3070_MIN_VERSION;
} else {
name = FIRMWARE_2870_FILENAME;
min_version = FIRMWARE_2870_MIN_VERSION;
}
dev = &((struct os_cookie *)adapter->OS_Cookie)->pUsb_Dev->dev;
#else /* RTMP_MAC_PCI */
if (IS_RT3090(adapter) || IS_RT3390(adapter)) {
name = FIRMWARE_3090_FILENAME;
min_version = FIRMWARE_3090_MIN_VERSION;
} else {
name = FIRMWARE_2860_FILENAME;
min_version = FIRMWARE_2860_MIN_VERSION;
}
dev = &((struct os_cookie *)adapter->OS_Cookie)->pci_dev->dev;
#endif
err = request_firmware(&fw, name, dev);
if (err) {
dev_err(dev, "firmware file %s request failed (%d)\n",
name, err);
return NULL;
}
if (fw->size < FIRMWAREIMAGE_LENGTH) {
dev_err(dev, "firmware file %s size is invalid\n", name);
goto invalid;
}
/* is it new enough? */
adapter->FirmwareVersion = fw->data[FIRMWAREIMAGE_LENGTH - 3];
if (adapter->FirmwareVersion < min_version) {
dev_err(dev,
"firmware file %s is too old;"
" driver requires v%d or later\n",
name, min_version);
goto invalid;
}
/* is the internal CRC correct? */
if (crc_ccitt(0xffff, fw->data, FIRMWAREIMAGE_LENGTH - 2) !=
(fw->data[FIRMWAREIMAGE_LENGTH - 2] |
(fw->data[FIRMWAREIMAGE_LENGTH - 1] << 8))) {
dev_err(dev, "firmware file %s failed internal CRC\n", name);
goto invalid;
}
adapter->firmware = fw;
return fw;
invalid:
release_firmware(fw);
return NULL;
}
/*
========================================================================
......@@ -109,46 +184,16 @@ int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd)
*/
int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd)
{
const struct firmware *fw;
int Status = NDIS_STATUS_SUCCESS;
u8 *pFirmwareImage = NULL;
unsigned long FileLength, Index;
unsigned long Index;
u32 MacReg = 0;
#ifdef RTMP_MAC_USB
u32 Version = (pAd->MACVersion >> 16);
#endif
/* New 8k byte firmware size for RT3071/RT3072 */
{
#ifdef RTMP_MAC_PCI
if (IS_RT3090(pAd) || IS_RT3390(pAd)) {
pFirmwareImage = FirmwareImage_3090;
FileLength = FIRMWAREIMAGE_MAX_LENGTH;
} else {
pFirmwareImage = FirmwareImage_2860;
FileLength = FIRMWAREIMAGE_MAX_LENGTH;
}
#endif /* RTMP_MAC_PCI // */
#ifdef RTMP_MAC_USB
/* the firmware image consists of two parts */
if ((Version != 0x2860) && (Version != 0x2872) && (Version != 0x3070)) { /* use the second part */
/*printk("KH:Use New Version,part2\n"); */
pFirmwareImage =
(u8 *)&
FirmwareImage_3070[FIRMWAREIMAGEV1_LENGTH];
FileLength = FIRMWAREIMAGEV2_LENGTH;
} else {
/*printk("KH:Use New Version,part1\n"); */
if (Version == 0x3070)
pFirmwareImage = FirmwareImage_3070;
else
pFirmwareImage = FirmwareImage_2870;
FileLength = FIRMWAREIMAGEV1_LENGTH;
}
#endif /* RTMP_MAC_USB // */
}
fw = rtmp_get_firmware(pAd);
if (!fw)
return NDIS_STATUS_FAILURE;
RTMP_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength);
RTMP_WRITE_FIRMWARE(pAd, fw->data, FIRMWAREIMAGE_LENGTH);
/* check if MCU is ready */
Index = 0;
......
......@@ -25,6 +25,7 @@
*************************************************************************
*/
#include <linux/firmware.h>
#include <linux/sched.h>
#include "rt_config.h"
......@@ -260,6 +261,8 @@ void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
NdisFreeSpinLock(&pAd->irq_lock);
release_firmware(pAd->firmware);
vfree(pAd); /* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
if (os_cookie)
kfree(os_cookie);
......
......@@ -1719,6 +1719,7 @@ struct rt_rtmp_adapter {
void *OS_Cookie; /* save specific structure relative to OS */
struct net_device *net_dev;
unsigned long VirtualIfCnt;
const struct firmware *firmware;
struct rt_rtmp_chip_op chipOps;
u16 ThisTbttNumToNextWakeUp;
......
......@@ -3,5 +3,7 @@ config RT2870
depends on USB && X86 && WLAN
select WIRELESS_EXT
select WEXT_PRIV
select CRC_CCITT
select FW_LOADER
---help---
This is an experimental driver for the Ralink xx70 wireless chips.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment