aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ar71xx/files/arch
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2015-04-07 20:03:35 +0000
committerGabor Juhos <juhosg@openwrt.org>2015-04-07 20:03:35 +0000
commit76b5a9aa7d9ca0dcd7369e302f943d7a128621da (patch)
tree896b47c256f062b82b318e7028472282a6711330 /target/linux/ar71xx/files/arch
parentf0cbd004ee3992c6c8cbee0466fa5a53bbf50e80 (diff)
downloadupstream-76b5a9aa7d9ca0dcd7369e302f943d7a128621da.tar.gz
upstream-76b5a9aa7d9ca0dcd7369e302f943d7a128621da.tar.bz2
upstream-76b5a9aa7d9ca0dcd7369e302f943d7a128621da.zip
ar71xx: routerboot: add support for extended radio data
On newer Mikrotik boards, the radio calibration data is stored differently and uses LZO compression instead of RLE. Update the RouterBOOT helper code to support the new format. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> SVN-Revision: 45297
Diffstat (limited to 'target/linux/ar71xx/files/arch')
-rw-r--r--target/linux/ar71xx/files/arch/mips/ath79/routerboot.c65
-rw-r--r--target/linux/ar71xx/files/arch/mips/ath79/routerboot.h6
2 files changed, 64 insertions, 7 deletions
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c
index dbdec02056..5853b157f3 100644
--- a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c
+++ b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.c
@@ -15,11 +15,13 @@
#include <linux/errno.h>
#include <linux/routerboot.h>
#include <linux/rle.h>
+#include <linux/lzo.h>
#include "routerboot.h"
#define RB_BLOCK_SIZE 0x1000
#define RB_ART_SIZE 0x10000
+#define RB_MAGIC_ERD 0x00455244 /* extended radio data */
static struct rb_info rb_info;
@@ -63,6 +65,7 @@ routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id,
u8 **tag_data, u16 *tag_len)
{
uint32_t magic;
+ bool align = false;
int ret;
if (buflen < 4)
@@ -70,6 +73,9 @@ routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id,
magic = get_u32(buf);
switch (magic) {
+ case RB_MAGIC_ERD:
+ align = true;
+ /* fall trough */
case RB_MAGIC_HARD:
/* skip magic value */
buf += 4;
@@ -121,6 +127,9 @@ routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id,
break;
}
+ if (align)
+ len = (len + 3) / 4;
+
buf += len;
buflen -= len;
}
@@ -168,13 +177,16 @@ rb_get_hw_options(void)
return get_u32(tag);
}
-__init void *
-rb_get_wlan_data(void)
+static void * __init
+__rb_get_wlan_data(u16 id)
{
u16 tag_len;
u8 *tag;
void *buf;
int err;
+ u32 magic;
+ size_t src_done;
+ size_t dst_done;
err = rb_find_hard_cfg_tag(RB_ID_WLAN_DATA, &tag, &tag_len);
if (err) {
@@ -188,11 +200,38 @@ rb_get_wlan_data(void)
goto err;
}
- err = rle_decode((char *) tag, tag_len, buf, RB_ART_SIZE,
- NULL, NULL);
- if (err) {
- pr_err("unable to decode calibration data\n");
- goto err_free;
+ magic = get_u32(tag);
+ if (magic == RB_MAGIC_ERD) {
+ u8 *erd_data;
+ u16 erd_len;
+
+ if (id == 0)
+ goto err_free;
+
+ err = routerboot_find_tag(tag, tag_len, id,
+ &erd_data, &erd_len);
+ if (err) {
+ pr_err("no ERD data found for id %u\n", id);
+ goto err_free;
+ }
+
+ dst_done = RB_ART_SIZE;
+ err = lzo1x_decompress_safe(erd_data, erd_len, buf, &dst_done);
+ if (err) {
+ pr_err("unable to decompress calibration data %d\n",
+ err);
+ goto err_free;
+ }
+ } else {
+ if (id != 0)
+ goto err_free;
+
+ err = rle_decode((char *) tag, tag_len, buf, RB_ART_SIZE,
+ &src_done, &dst_done);
+ if (err) {
+ pr_err("unable to decode calibration data\n");
+ goto err_free;
+ }
}
return buf;
@@ -203,6 +242,18 @@ err:
return NULL;
}
+__init void *
+rb_get_wlan_data(void)
+{
+ return __rb_get_wlan_data(0);
+}
+
+__init void *
+rb_get_ext_wlan_data(u16 id)
+{
+ return __rb_get_wlan_data(id);
+}
+
__init const struct rb_info *
rb_init_info(void *data, unsigned int size)
{
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h
index 6ec296afd4..c1d7fb9ee0 100644
--- a/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h
+++ b/target/linux/ar71xx/files/arch/mips/ath79/routerboot.h
@@ -24,6 +24,7 @@ struct rb_info {
#ifdef CONFIG_ATH79_ROUTERBOOT
const struct rb_info *rb_init_info(void *data, unsigned int size);
void *rb_get_wlan_data(void);
+void *rb_get_ext_wlan_data(u16 id);
int routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id,
u8 **tag_data, u16 *tag_len);
@@ -40,6 +41,11 @@ static inline void *rb_get_wlan_data(void)
return NULL;
}
+static inline void *rb_get_wlan_data(u16 id)
+{
+ return NULL;
+}
+
static inline int
routerboot_find_tag(u8 *buf, unsigned int buflen, u16 tag_id,
u8 **tag_data, u16 *tag_len)