mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 00:21:59 +00:00
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
@ -28,6 +28,7 @@ config RT2X00_LIB_USB
|
||||
config RT2X00_LIB_FIRMWARE
|
||||
boolean
|
||||
depends on RT2X00_LIB
|
||||
select CRC_CCITT
|
||||
select CRC_ITU_T
|
||||
select FW_LOADER
|
||||
|
||||
|
@ -551,6 +551,8 @@ enum rt2x00_flags {
|
||||
* Driver features
|
||||
*/
|
||||
DRIVER_REQUIRE_FIRMWARE,
|
||||
DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T,
|
||||
DRIVER_REQUIRE_FIRMWARE_CCITT,
|
||||
DRIVER_REQUIRE_BEACON_GUARD,
|
||||
DRIVER_REQUIRE_ATIM_QUEUE,
|
||||
|
||||
|
@ -1017,11 +1017,9 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
|
||||
* If this is the first interface which is added,
|
||||
* we should load the firmware now.
|
||||
*/
|
||||
if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
|
||||
retval = rt2x00lib_load_firmware(rt2x00dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
retval = rt2x00lib_load_firmware(rt2x00dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* Initialize the device.
|
||||
|
@ -23,6 +23,7 @@
|
||||
Abstract: rt2x00 firmware loading routines.
|
||||
*/
|
||||
|
||||
#include <linux/crc-ccitt.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@ -37,7 +38,6 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
|
||||
char *fw_name;
|
||||
int retval;
|
||||
u16 crc;
|
||||
u16 tmp;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* The last 2 bytes of the firmware are the CRC
|
||||
* so substract those 2 bytes from the CRC checksum,
|
||||
* and set those 2 bytes to 0 when calculating CRC.
|
||||
* Perform crc validation on the firmware.
|
||||
* The last 2 bytes in the firmware array are the crc checksum itself,
|
||||
* this means that we should never pass those 2 bytes to the crc
|
||||
* algorithm.
|
||||
*/
|
||||
tmp = 0;
|
||||
crc = crc_itu_t(0, fw->data, fw->size - 2);
|
||||
crc = crc_itu_t(crc, (u8 *)&tmp, 2);
|
||||
if (test_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags)) {
|
||||
/*
|
||||
* 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])) {
|
||||
ERROR(rt2x00dev, "Firmware CRC error.\n");
|
||||
ERROR(rt2x00dev, "Firmware checksum error.\n");
|
||||
retval = -ENOENT;
|
||||
goto exit;
|
||||
}
|
||||
@ -96,6 +116,9 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
if (!rt2x00dev->fw) {
|
||||
retval = rt2x00lib_request_firmware(rt2x00dev);
|
||||
if (retval)
|
||||
|
@ -2258,9 +2258,10 @@ static int rt61pci_probe_hw(struct rt2x00_dev *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_CRC_ITU_T, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Set the rssi offset.
|
||||
|
@ -1849,9 +1849,10 @@ static int rt73usb_probe_hw(struct rt2x00_dev *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_CRC_ITU_T, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Set the rssi offset.
|
||||
|
Loading…
Reference in New Issue
Block a user