[PATCH 7/8] ath10k-ct: Support qcom,ath10k-calibration-data-base64
Brian Norris
computersforpeace at gmail.com
Mon Jan 2 15:25:33 PST 2023
See the patch notes about the stock firmware for TP-Link Onhub and
https://chromium-review.googlesource.com/243115.
As noted there, the production firmware for Google OnHub devices only
provide the *-base64 Device Tree property, and so either the kernel or
some user space mechanism needs to know how to parse/convert this
property.
I haven't submitted this patch upstream. However, it applies relatively
cleanly to the tree even after almost 8 years, so it doesn't seem too
hard to maintain.
Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
.../970-ath10k-calibration-base64.patch | 249 ++++++++++++++++++
1 file changed, 249 insertions(+)
create mode 100644 package/kernel/ath10k-ct/patches/970-ath10k-calibration-base64.patch
diff --git a/package/kernel/ath10k-ct/patches/970-ath10k-calibration-base64.patch b/package/kernel/ath10k-ct/patches/970-ath10k-calibration-base64.patch
new file mode 100644
index 000000000000..739bdee9ccf4
--- /dev/null
+++ b/package/kernel/ath10k-ct/patches/970-ath10k-calibration-base64.patch
@@ -0,0 +1,249 @@
+Adapted from:
+https://chromium-review.googlesource.com/307062
+
+This "hack" remained in the production kernel, and so the production firmware
+for Google OnHub still only knows how to patch the *-base64 Device Tree
+property.
+
+CHROMIUM: HACK: ath10k: read calibration data in base64 format from DT
+
+ Chrome OS firmware doesn't support binary format in VPD currently.
+ As a workaround, the firmware stores the calibration data in base64
+ format in the same node with the different name:
+
+ qcom,ath10k-calibration-data-base64 = [ 01 02 03 ... ];
+
+ Since the original property "qcom,ath10k-calibration-data" is always
+ looked for first, it should have an invalid size (e.g. 1).
+
+ BUG=chrome-os-partner:35262
+ TEST=build/boot on storm suceeded. Setup Storm board as AP using
+ hostapd and
+ connected to the board using another device. Device was able to
+ connect to
+ the internet and load multiple websites.
+
+ Change-Id: I95675a803fad3b94977ecd0977bd9980779ad7e9
+ Signed-off-by: Toshi Kikuchi <toshik at chromium.org>
+ Reviewed-on: https://chromium-review.googlesource.com/243115
+ Reviewed-by: Grant Grundler <grundler at chromium.org>
+
+Change-Id: I17874f0ed03e28d279b08fe70aca70af57c90bda
+Signed-off-by: Anilkumar Kolli <akolli at codeaurora.org>
+Reviewed-on: https://chromium-review.googlesource.com/307062
+Commit-Ready: Grant Grundler <grundler at chromium.org>
+Tested-by: Grant Grundler <grundler at chromium.org>
+Reviewed-by: Srinivasa duvvuri <sduvvuri at chromium.org>
+Reviewed-by: Grant Grundler <grundler at chromium.org>
+--- a/ath10k-5.15/Makefile
++++ b/ath10k-5.15/Makefile
+@@ -4,6 +4,7 @@ ath10k_core-y += mac.o \
+ debug.o \
+ core.o \
+ coredump.o \
++ decode64.o \
+ htc.o \
+ htt.o \
+ htt_rx.o \
+--- a/ath10k-5.15/core.c
++++ b/ath10k-5.15/core.c
+@@ -18,6 +18,7 @@
+ #include <linux/ctype.h>
+
+ #include "core.h"
++#include "decode64.h"
+ #include "mac.h"
+ #include "htc.h"
+ #include "hif.h"
+@@ -2167,6 +2168,73 @@ static int ath10k_download_cal_file(stru
+ return 0;
+ }
+
++static int ath10k_download_cal_dt_base64(struct ath10k *ar)
++{
++ struct device_node *node;
++ int data_len;
++ void *data;
++ int ret;
++
++ node = ar->dev->of_node;
++ if (!node)
++ /* Device Tree is optional, don't print any warnings if
++ * there's no node for ath10k.
++ */
++ return -ENOENT;
++
++ if (!of_get_property(node, "qcom,ath10k-calibration-data-base64",
++ &data_len)) {
++ /* The calibration data node is optional */
++ return -ENOENT;
++ }
++
++ data = kmalloc(data_len, GFP_KERNEL);
++ if (!data) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ ret = of_property_read_u8_array(node,
++ "qcom,ath10k-calibration-data-base64",
++ data, data_len);
++ if (ret) {
++ ath10k_warn(ar,
++ "failed to read calibration data (base64) from DT: %d\n",
++ ret);
++ goto out_free;
++ }
++
++ data_len = strip_nl(data, data + data_len, data);
++ data_len = decode64(data, data + data_len, data);
++ if (data_len < 0) {
++ ath10k_warn(ar,
++ "base64 decoder found invalid input\n");
++ ret = -EINVAL;
++ goto out_free;
++ }
++
++ if (data_len != ar->hw_params.cal_data_len) {
++ ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
++ data_len);
++ ret = -EMSGSIZE;
++ goto out_free;
++ }
++
++ ret = ath10k_download_board_data(ar, data, data_len);
++ if (ret) {
++ ath10k_warn(ar, "failed to download base64 calibration data from Device Tree: %d\n",
++ ret);
++ goto out_free;
++ }
++
++ ret = 0;
++out_free:
++ kfree(data);
++
++out:
++ return ret;
++}
++
+ static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
+ {
+ struct device_node *node;
+@@ -2787,6 +2855,12 @@ static int ath10k_download_cal_data(stru
+ "boot did not find target EEPROM entry, try OTP next: %d\n",
+ ret);
+
++ ret = ath10k_download_cal_dt_base64(ar);
++ if (ret == 0) {
++ ar->cal_mode = ATH10K_CAL_MODE_DT;
++ goto done;
++ }
++
+ ret = ath10k_download_and_run_otp(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to run otp: %d (download-cal-data)\n", ret);
+--- /dev/null
++++ b/ath10k-5.15/decode64.c
+@@ -0,0 +1,89 @@
++/*
++ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
++ * Copyright (c) 2014, The Chromium OS Authors
++ *
++ * 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
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include "decode64.h"
++
++static char revkey[128] = {
++ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
++ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
++ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
++ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
++ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
++ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
++ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
++ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
++};
++
++int
++decode64(unsigned char *src, unsigned char *src_end, unsigned char *dst)
++{
++ unsigned char *dst_end = dst;
++
++ while (&src[3] < src_end) {
++ int x;
++ int t[4];
++ int i;
++
++ if (src[0] == '=' || src[1] == '=' ||
++ (src[2] == '=' && src[3] != '=')) {
++ return -1;
++ }
++
++ for (i = 0; i < 4; i++) {
++ if (src[i] == '=') {
++ t[i] = 0;
++ } else {
++ if (src[i] >= 128 ||
++ ((t[i] = revkey[src[i]]) < 0)) {
++ return -1;
++ }
++ }
++ }
++
++ x = (t[0] << 18) + (t[1] << 12) + (t[2] << 6) + t[3];
++
++ *dst_end++ = (x >> 16) & 0xff;
++ if (src[2] != '=')
++ *dst_end++ = (x >> 8) & 0xff;
++ if (src[3] != '=')
++ *dst_end++ = x & 0xff;
++
++ src += 4;
++ }
++
++ if (src != src_end)
++ return -1;
++
++ return dst_end - dst;
++}
++
++int
++strip_nl(unsigned char *src, unsigned char *src_end, unsigned char *dst)
++{
++ unsigned char *dst_end = dst;
++
++ while (src < src_end) {
++ if (*src != '\n')
++ *dst_end++ = *src;
++ src++;
++ }
++
++ return dst_end - dst;
++}
+--- /dev/null
++++ b/ath10k-5.15/decode64.h
+@@ -0,0 +1,10 @@
++#ifndef _DECODE64_H_
++#define _DECODE64_H_
++
++int decode64(unsigned char *src, unsigned char *src_end,
++ unsigned char *dst);
++
++int strip_nl(unsigned char *src, unsigned char *src_end,
++ unsigned char *dst);
++
++#endif /* _DECODE64_H_ */
--
2.39.0
More information about the openwrt-devel
mailing list