diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2011-08-30 12:50:25 +0200 |
---|---|---|
committer | Stanislaw Gruszka <sgruszka@redhat.com> | 2011-11-15 12:41:53 +0100 |
commit | 862d32e6db6183e5cb67fe465818578556196a94 (patch) | |
tree | f693bc0dcaf396a7918c96c79509167ed1391771 /drivers/net/wireless/iwlegacy/4965.c | |
parent | 56e7a8cca0fd9e096acd2233f0e9f95df6423071 (diff) |
iwlegacy: merge iwl-4965-ucode.c into 4965.c
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Diffstat (limited to 'drivers/net/wireless/iwlegacy/4965.c')
-rw-r--r-- | drivers/net/wireless/iwlegacy/4965.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index a4b42cc4c4c7..752564d36c98 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -47,6 +47,131 @@ #include "iwl-4965.h" #include "iwl-4965-debugfs.h" +#define IL_AC_UNSET -1 + +/** + * il_verify_inst_sparse - verify runtime uCode image in card vs. host, + * using sample data 100 bytes apart. If these sample points are good, + * it's a pretty good bet that everything between them is good, too. + */ +static int +il4965_verify_inst_sparse(struct il_priv *il, __le32 *image, u32 len) +{ + u32 val; + int ret = 0; + u32 errcnt = 0; + u32 i; + + D_INFO("ucode inst image size is %u\n", len); + + for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { + /* read data comes through single port, auto-incr addr */ + /* NOTE: Use the debugless read so we don't flood kernel log + * if IL_DL_IO is set */ + il_wr(il, HBUS_TARG_MEM_RADDR, + i + IL4965_RTC_INST_LOWER_BOUND); + val = _il_rd(il, HBUS_TARG_MEM_RDAT); + if (val != le32_to_cpu(*image)) { + ret = -EIO; + errcnt++; + if (errcnt >= 3) + break; + } + } + + return ret; +} + +/** + * il4965_verify_inst_full - verify runtime uCode image in card vs. host, + * looking at all data. + */ +static int il4965_verify_inst_full(struct il_priv *il, __le32 *image, + u32 len) +{ + u32 val; + u32 save_len = len; + int ret = 0; + u32 errcnt; + + D_INFO("ucode inst image size is %u\n", len); + + il_wr(il, HBUS_TARG_MEM_RADDR, + IL4965_RTC_INST_LOWER_BOUND); + + errcnt = 0; + for (; len > 0; len -= sizeof(u32), image++) { + /* read data comes through single port, auto-incr addr */ + /* NOTE: Use the debugless read so we don't flood kernel log + * if IL_DL_IO is set */ + val = _il_rd(il, HBUS_TARG_MEM_RDAT); + if (val != le32_to_cpu(*image)) { + IL_ERR("uCode INST section is invalid at " + "offset 0x%x, is 0x%x, s/b 0x%x\n", + save_len - len, val, le32_to_cpu(*image)); + ret = -EIO; + errcnt++; + if (errcnt >= 20) + break; + } + } + + if (!errcnt) + D_INFO( + "ucode image in INSTRUCTION memory is good\n"); + + return ret; +} + +/** + * il4965_verify_ucode - determine which instruction image is in SRAM, + * and verify its contents + */ +int il4965_verify_ucode(struct il_priv *il) +{ + __le32 *image; + u32 len; + int ret; + + /* Try bootstrap */ + image = (__le32 *)il->ucode_boot.v_addr; + len = il->ucode_boot.len; + ret = il4965_verify_inst_sparse(il, image, len); + if (!ret) { + D_INFO("Bootstrap uCode is good in inst SRAM\n"); + return 0; + } + + /* Try initialize */ + image = (__le32 *)il->ucode_init.v_addr; + len = il->ucode_init.len; + ret = il4965_verify_inst_sparse(il, image, len); + if (!ret) { + D_INFO("Initialize uCode is good in inst SRAM\n"); + return 0; + } + + /* Try runtime/protocol */ + image = (__le32 *)il->ucode_code.v_addr; + len = il->ucode_code.len; + ret = il4965_verify_inst_sparse(il, image, len); + if (!ret) { + D_INFO("Runtime uCode is good in inst SRAM\n"); + return 0; + } + + IL_ERR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); + + /* Since nothing seems to match, show first several data entries in + * instruction SRAM, so maybe visual inspection will give a clue. + * Selection of bootstrap image (vs. other images) is arbitrary. */ + image = (__le32 *)il->ucode_boot.v_addr; + len = il->ucode_boot.len; + ret = il4965_verify_inst_full(il, image, len); + + return ret; +} + /****************************************************************************** * * EEPROM related functions |