2007-09-25 17:57:13 -07:00
/*
2009-11-08 16:39:55 +01:00
Copyright ( C ) 2004 - 2009 Ivo van Doorn < IvDoorn @ gmail . com >
Copyright ( C ) 2004 - 2009 Gertjan van Wingerde < gwingerde @ gmail . com >
2007-09-25 17:57:13 -07:00
< http : //rt2x00.serialmonkey.com>
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2013-12-06 03:32:11 -08:00
along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2007-09-25 17:57:13 -07:00
*/
/*
Module : rt2x00lib
Abstract : rt2x00 firmware loading routines .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include "rt2x00.h"
# include "rt2x00lib.h"
static int rt2x00lib_request_firmware ( struct rt2x00_dev * rt2x00dev )
{
struct device * device = wiphy_dev ( rt2x00dev - > hw - > wiphy ) ;
const struct firmware * fw ;
char * fw_name ;
int retval ;
/*
* Read correct firmware from harddisk .
*/
fw_name = rt2x00dev - > ops - > lib - > get_firmware_name ( rt2x00dev ) ;
if ( ! fw_name ) {
2013-04-19 08:33:40 -07:00
rt2x00_err ( rt2x00dev ,
" Invalid firmware filename \n "
" Please file bug report to %s \n " , DRV_PROJECT ) ;
2007-09-25 17:57:13 -07:00
return - EINVAL ;
}
2013-04-19 08:33:40 -07:00
rt2x00_info ( rt2x00dev , " Loading firmware file '%s' \n " , fw_name ) ;
2007-09-25 17:57:13 -07:00
retval = request_firmware ( & fw , fw_name , device ) ;
if ( retval ) {
2013-04-19 08:33:40 -07:00
rt2x00_err ( rt2x00dev , " Failed to request Firmware \n " ) ;
2007-09-25 17:57:13 -07:00
return retval ;
}
if ( ! fw | | ! fw - > size | | ! fw - > data ) {
2013-04-19 08:33:40 -07:00
rt2x00_err ( rt2x00dev , " Failed to read Firmware \n " ) ;
2011-01-11 00:47:44 +01:00
release_firmware ( fw ) ;
2007-09-25 17:57:13 -07:00
return - ENOENT ;
}
2013-04-19 08:33:40 -07:00
rt2x00_info ( rt2x00dev , " Firmware detected - version: %d.%d \n " ,
fw - > data [ fw - > size - 4 ] , fw - > data [ fw - > size - 3 ] ) ;
2010-07-29 13:50:39 -04:00
snprintf ( rt2x00dev - > hw - > wiphy - > fw_version ,
sizeof ( rt2x00dev - > hw - > wiphy - > fw_version ) , " %d.%d " ,
fw - > data [ fw - > size - 4 ] , fw - > data [ fw - > size - 3 ] ) ;
2007-09-25 17:57:13 -07:00
2009-01-28 00:33:47 +01:00
retval = rt2x00dev - > ops - > lib - > check_firmware ( rt2x00dev , fw - > data , fw - > size ) ;
switch ( retval ) {
case FW_OK :
break ;
case FW_BAD_CRC :
2013-04-19 08:33:40 -07:00
rt2x00_err ( rt2x00dev , " Firmware checksum error \n " ) ;
2009-01-28 00:33:47 +01:00
goto exit ;
case FW_BAD_LENGTH :
2013-04-19 08:33:40 -07:00
rt2x00_err ( rt2x00dev , " Invalid firmware file length (len=%zu) \n " ,
fw - > size ) ;
2009-01-28 00:33:47 +01:00
goto exit ;
case FW_BAD_VERSION :
2013-04-19 08:33:40 -07:00
rt2x00_err ( rt2x00dev , " Current firmware does not support detected chipset \n " ) ;
2009-01-28 00:33:47 +01:00
goto exit ;
2010-05-17 22:47:34 -07:00
}
2009-01-28 00:33:47 +01:00
2007-09-25 17:57:13 -07:00
rt2x00dev - > fw = fw ;
return 0 ;
exit :
release_firmware ( fw ) ;
2009-01-28 00:33:47 +01:00
return - ENOENT ;
2007-09-25 17:57:13 -07:00
}
int rt2x00lib_load_firmware ( struct rt2x00_dev * rt2x00dev )
{
int retval ;
2014-12-26 16:19:18 +08:00
if ( ! rt2x00_has_cap_flag ( rt2x00dev , REQUIRE_FIRMWARE ) )
2008-02-03 15:48:38 +01:00
return 0 ;
2007-09-25 17:57:13 -07:00
if ( ! rt2x00dev - > fw ) {
retval = rt2x00lib_request_firmware ( rt2x00dev ) ;
if ( retval )
return retval ;
}
/*
* Send firmware to the device .
*/
retval = rt2x00dev - > ops - > lib - > load_firmware ( rt2x00dev ,
rt2x00dev - > fw - > data ,
rt2x00dev - > fw - > size ) ;
2008-07-13 10:07:48 +02:00
/*
* 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 ) ;
2007-09-25 17:57:13 -07:00
return retval ;
}
void rt2x00lib_free_firmware ( struct rt2x00_dev * rt2x00dev )
{
release_firmware ( rt2x00dev - > fw ) ;
rt2x00dev - > fw = NULL ;
}