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 ...@@ -3,6 +3,8 @@ config RT2860
depends on PCI && X86 && WLAN depends on PCI && X86 && WLAN
select WIRELESS_EXT select WIRELESS_EXT
select WEXT_PRIV select WEXT_PRIV
select CRC_CCITT
select FW_LOADER
---help--- ---help---
This is an experimental driver for the Ralink 2860 and 3090 This is an experimental driver for the Ralink 2860 and 3090
wireless chips. wireless chips.
This diff is collapsed.
This diff is collapsed.
...@@ -37,35 +37,38 @@ ...@@ -37,35 +37,38 @@
#include "../rt_config.h" #include "../rt_config.h"
#if defined(RT2860) || defined(RT3090) #include <linux/crc-ccitt.h>
#include "firmware.h" #include <linux/firmware.h>
#include "../../rt3090/firmware.h"
#endif
#ifdef RT2870
#include "../../rt3070/firmware.h"
#include "firmware_3070.h"
#endif
#include <linux/bitrev.h>
#ifdef RTMP_MAC_USB #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_LENGTH 0x1000
#define FIRMWAREIMAGE_MAX_LENGTH 0x2000
#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(u8))
#define FIRMWARE_MAJOR_VERSION 0
#define FIRMWAREIMAGEV1_LENGTH 0x1000 #define FIRMWARE_2870_MIN_VERSION 12
#define FIRMWAREIMAGEV2_LENGTH 0x1000 #define FIRMWARE_2870_FILENAME "rt2870.bin"
MODULE_FIRMWARE(FIRMWARE_2870_FILENAME);
#ifdef RTMP_MAC_PCI #define FIRMWARE_3070_MIN_VERSION 17
#define FIRMWARE_MINOR_VERSION 2 #define FIRMWARE_3070_FILENAME "rt3070.bin"
#endif /* RTMP_MAC_PCI // */ 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) ...@@ -90,6 +93,78 @@ int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd)
return 0; 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) ...@@ -109,46 +184,16 @@ int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd)
*/ */
int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd) int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd)
{ {
const struct firmware *fw;
int Status = NDIS_STATUS_SUCCESS; int Status = NDIS_STATUS_SUCCESS;
u8 *pFirmwareImage = NULL; unsigned long Index;
unsigned long FileLength, Index;
u32 MacReg = 0; u32 MacReg = 0;
#ifdef RTMP_MAC_USB
u32 Version = (pAd->MACVersion >> 16);
#endif
/* New 8k byte firmware size for RT3071/RT3072 */ fw = rtmp_get_firmware(pAd);
{ if (!fw)
#ifdef RTMP_MAC_PCI return NDIS_STATUS_FAILURE;
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 // */
}
RTMP_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength); RTMP_WRITE_FIRMWARE(pAd, fw->data, FIRMWAREIMAGE_LENGTH);
/* check if MCU is ready */ /* check if MCU is ready */
Index = 0; Index = 0;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
************************************************************************* *************************************************************************
*/ */
#include <linux/firmware.h>
#include <linux/sched.h> #include <linux/sched.h>
#include "rt_config.h" #include "rt_config.h"
...@@ -260,6 +261,8 @@ void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd) ...@@ -260,6 +261,8 @@ void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
NdisFreeSpinLock(&pAd->irq_lock); 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); */ vfree(pAd); /* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
if (os_cookie) if (os_cookie)
kfree(os_cookie); kfree(os_cookie);
......
...@@ -1719,6 +1719,7 @@ struct rt_rtmp_adapter { ...@@ -1719,6 +1719,7 @@ struct rt_rtmp_adapter {
void *OS_Cookie; /* save specific structure relative to OS */ void *OS_Cookie; /* save specific structure relative to OS */
struct net_device *net_dev; struct net_device *net_dev;
unsigned long VirtualIfCnt; unsigned long VirtualIfCnt;
const struct firmware *firmware;
struct rt_rtmp_chip_op chipOps; struct rt_rtmp_chip_op chipOps;
u16 ThisTbttNumToNextWakeUp; u16 ThisTbttNumToNextWakeUp;
......
...@@ -3,5 +3,7 @@ config RT2870 ...@@ -3,5 +3,7 @@ config RT2870
depends on USB && X86 && WLAN depends on USB && X86 && WLAN
select WIRELESS_EXT select WIRELESS_EXT
select WEXT_PRIV select WEXT_PRIV
select CRC_CCITT
select FW_LOADER
---help--- ---help---
This is an experimental driver for the Ralink xx70 wireless chips. 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