rt2x00: Driver requiring firmware should select crc algo
The driver should select what CRC algorithm is required when performing a checksum on the firmware. rt61pci & rt73usb require crc-itu-t rt2800pci & rt2800usb require crc-ccitt Legacy 2800pci/usb driver uses crc-itu-t + bit order reversion, but that is just inefficient especially since the end result is the same as a different algorithm which is also available as library. ;) Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
adfdbb79c0
commit
9404ef34e4
6 changed files with 42 additions and 16 deletions
|
@ -28,6 +28,7 @@ config RT2X00_LIB_USB
|
||||||
config RT2X00_LIB_FIRMWARE
|
config RT2X00_LIB_FIRMWARE
|
||||||
boolean
|
boolean
|
||||||
depends on RT2X00_LIB
|
depends on RT2X00_LIB
|
||||||
|
select CRC_CCITT
|
||||||
select CRC_ITU_T
|
select CRC_ITU_T
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
|
|
||||||
|
|
|
@ -551,6 +551,8 @@ enum rt2x00_flags {
|
||||||
* Driver features
|
* Driver features
|
||||||
*/
|
*/
|
||||||
DRIVER_REQUIRE_FIRMWARE,
|
DRIVER_REQUIRE_FIRMWARE,
|
||||||
|
DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T,
|
||||||
|
DRIVER_REQUIRE_FIRMWARE_CCITT,
|
||||||
DRIVER_REQUIRE_BEACON_GUARD,
|
DRIVER_REQUIRE_BEACON_GUARD,
|
||||||
DRIVER_REQUIRE_ATIM_QUEUE,
|
DRIVER_REQUIRE_ATIM_QUEUE,
|
||||||
|
|
||||||
|
|
|
@ -1017,11 +1017,9 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
|
||||||
* If this is the first interface which is added,
|
* If this is the first interface which is added,
|
||||||
* we should load the firmware now.
|
* we should load the firmware now.
|
||||||
*/
|
*/
|
||||||
if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
|
retval = rt2x00lib_load_firmware(rt2x00dev);
|
||||||
retval = rt2x00lib_load_firmware(rt2x00dev);
|
if (retval)
|
||||||
if (retval)
|
return retval;
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the device.
|
* Initialize the device.
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
Abstract: rt2x00 firmware loading routines.
|
Abstract: rt2x00 firmware loading routines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/crc-ccitt.h>
|
||||||
#include <linux/crc-itu-t.h>
|
#include <linux/crc-itu-t.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -37,7 +38,6 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
|
||||||
char *fw_name;
|
char *fw_name;
|
||||||
int retval;
|
int retval;
|
||||||
u16 crc;
|
u16 crc;
|
||||||
u16 tmp;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read correct firmware from harddisk.
|
* Read correct firmware from harddisk.
|
||||||
|
@ -64,17 +64,37 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validate the firmware using 16 bit CRC.
|
* Perform crc validation on the firmware.
|
||||||
* The last 2 bytes of the firmware are the CRC
|
* The last 2 bytes in the firmware array are the crc checksum itself,
|
||||||
* so substract those 2 bytes from the CRC checksum,
|
* this means that we should never pass those 2 bytes to the crc
|
||||||
* and set those 2 bytes to 0 when calculating CRC.
|
* algorithm.
|
||||||
*/
|
*/
|
||||||
tmp = 0;
|
if (test_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags)) {
|
||||||
crc = crc_itu_t(0, fw->data, fw->size - 2);
|
/*
|
||||||
crc = crc_itu_t(crc, (u8 *)&tmp, 2);
|
* Use the crc itu-t algorithm.
|
||||||
|
* Use 0 for the last 2 bytes to complete the checksum.
|
||||||
|
*/
|
||||||
|
crc = crc_itu_t(0, fw->data, fw->size - 2);
|
||||||
|
crc = crc_itu_t_byte(crc, 0);
|
||||||
|
crc = crc_itu_t_byte(crc, 0);
|
||||||
|
} else if (test_bit(DRIVER_REQUIRE_FIRMWARE_CCITT, &rt2x00dev->flags)) {
|
||||||
|
/*
|
||||||
|
* Use the crc ccitt algorithm.
|
||||||
|
* This will return the same value as the legacy driver which
|
||||||
|
* used bit ordering reversion on the both the firmware bytes
|
||||||
|
* before input input as well as on the final output.
|
||||||
|
* Obviously using crc ccitt directly is much more efficient.
|
||||||
|
*/
|
||||||
|
crc = crc_ccitt(~0, fw->data, fw->size - 2);
|
||||||
|
} else {
|
||||||
|
ERROR(rt2x00dev, "No checksum algorithm selected "
|
||||||
|
"for firmware validation.\n");
|
||||||
|
retval = -ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
|
if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
|
||||||
ERROR(rt2x00dev, "Firmware CRC error.\n");
|
ERROR(rt2x00dev, "Firmware checksum error.\n");
|
||||||
retval = -ENOENT;
|
retval = -ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -96,6 +116,9 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!rt2x00dev->fw) {
|
if (!rt2x00dev->fw) {
|
||||||
retval = rt2x00lib_request_firmware(rt2x00dev);
|
retval = rt2x00lib_request_firmware(rt2x00dev);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
|
|
@ -2258,9 +2258,10 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||||
rt61pci_probe_hw_mode(rt2x00dev);
|
rt61pci_probe_hw_mode(rt2x00dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This device requires firmware
|
* This device requires firmware.
|
||||||
*/
|
*/
|
||||||
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
||||||
|
__set_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the rssi offset.
|
* Set the rssi offset.
|
||||||
|
|
|
@ -1849,9 +1849,10 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||||
rt73usb_probe_hw_mode(rt2x00dev);
|
rt73usb_probe_hw_mode(rt2x00dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This device requires firmware
|
* This device requires firmware.
|
||||||
*/
|
*/
|
||||||
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
||||||
|
__set_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the rssi offset.
|
* Set the rssi offset.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue