aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rt2x00/rt2x00firmware.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00firmware.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00firmware.c77
1 files changed, 41 insertions, 36 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index 236025f8b90..fbae2799e3e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -1,5 +1,6 @@
/*
- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+ Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@@ -13,9 +14,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the
- Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
@@ -23,12 +22,6 @@
Abstract: rt2x00 firmware loading routines.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
-#include <linux/crc-itu-t.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -41,52 +34,54 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
const struct firmware *fw;
char *fw_name;
int retval;
- u16 crc;
- u16 tmp;
/*
* Read correct firmware from harddisk.
*/
fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev);
if (!fw_name) {
- ERROR(rt2x00dev,
- "Invalid firmware filename.\n"
- "Please file bug report to %s.\n", DRV_PROJECT);
+ rt2x00_err(rt2x00dev,
+ "Invalid firmware filename\n"
+ "Please file bug report to %s\n", DRV_PROJECT);
return -EINVAL;
}
- INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
+ rt2x00_info(rt2x00dev, "Loading firmware file '%s'\n", fw_name);
retval = request_firmware(&fw, fw_name, device);
if (retval) {
- ERROR(rt2x00dev, "Failed to request Firmware.\n");
+ rt2x00_err(rt2x00dev, "Failed to request Firmware\n");
return retval;
}
if (!fw || !fw->size || !fw->data) {
- ERROR(rt2x00dev, "Failed to read Firmware.\n");
+ rt2x00_err(rt2x00dev, "Failed to read Firmware\n");
+ release_firmware(fw);
return -ENOENT;
}
- /*
- * 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.
- */
- tmp = 0;
- crc = crc_itu_t(0, fw->data, fw->size - 2);
- crc = crc_itu_t(crc, (u8 *)&tmp, 2);
-
- if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
- ERROR(rt2x00dev, "Firmware CRC error.\n");
- retval = -ENOENT;
+ rt2x00_info(rt2x00dev, "Firmware detected - version: %d.%d\n",
+ fw->data[fw->size - 4], fw->data[fw->size - 3]);
+ snprintf(rt2x00dev->hw->wiphy->fw_version,
+ sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",
+ fw->data[fw->size - 4], fw->data[fw->size - 3]);
+
+ retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size);
+ switch (retval) {
+ case FW_OK:
+ break;
+ case FW_BAD_CRC:
+ rt2x00_err(rt2x00dev, "Firmware checksum error\n");
+ goto exit;
+ case FW_BAD_LENGTH:
+ rt2x00_err(rt2x00dev, "Invalid firmware file length (len=%zu)\n",
+ fw->size);
+ goto exit;
+ case FW_BAD_VERSION:
+ rt2x00_err(rt2x00dev, "Current firmware does not support detected chipset\n");
goto exit;
}
- INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
- fw->data[fw->size - 4], fw->data[fw->size - 3]);
-
rt2x00dev->fw = fw;
return 0;
@@ -94,13 +89,16 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
exit:
release_firmware(fw);
- return retval;
+ return -ENOENT;
}
int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags))
+ return 0;
+
if (!rt2x00dev->fw) {
retval = rt2x00lib_request_firmware(rt2x00dev);
if (retval)
@@ -113,6 +111,14 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev,
rt2x00dev->fw->data,
rt2x00dev->fw->size);
+
+ /*
+ * When the firmware is uploaded to the hardware the LED
+ * association status might have been triggered, for correct
+ * LED handling it should now be reset.
+ */
+ rt2x00leds_led_assoc(rt2x00dev, false);
+
return retval;
}
@@ -121,4 +127,3 @@ void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
release_firmware(rt2x00dev->fw);
rt2x00dev->fw = NULL;
}
-