diff mbox series

[OpenWrt-Devel] ipq806x: add ath10k calibration data MAC addresses patching

Message ID 20181028163943.9957-1-chunkeey@gmail.com
State Not Applicable, archived
Headers show
Series [OpenWrt-Devel] ipq806x: add ath10k calibration data MAC addresses patching | expand

Commit Message

Christian Lamparter Oct. 28, 2018, 4:39 p.m. UTC
Ben Greear reported in his patch:
|Subject: netgear r7800: Fix mac address of radios.
|
|Reloading the driver causes the phyX to change, and that
|caused the MAC address to change.

This is because all ODM/OEMs except QCA bothered to write
the correct MAC address for the ath10k wifi into the
calibration data.

This patch copies over the MAC patching helper functions from ipq40xx's
target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
file and converts all the devices to patch the correct MACs into the
extracted calibration data before it gets sent to the driver, which sets
up the device with the correct MAC address. It also removes the
10_fix_wifi_mac file as it has served its purpose.

Please note the C2600: There is conflicting information on what
the offset for the second wifi is supposed to be. This patch uses
what was specified in 10_fix_wifi_mac.

Reported-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
---
 .../etc/hotplug.d/firmware/11-ath10k-caldata  | 64 +++++++++++++++++--
 .../etc/hotplug.d/ieee80211/10_fix_wifi_mac   | 37 -----------
 2 files changed, 57 insertions(+), 44 deletions(-)
 delete mode 100644 target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac

Comments

Felix Fietkau Nov. 1, 2018, 10:18 a.m. UTC | #1
On 2018-10-28 17:39, Christian Lamparter wrote:
> Ben Greear reported in his patch:
> |Subject: netgear r7800: Fix mac address of radios.
> |
> |Reloading the driver causes the phyX to change, and that
> |caused the MAC address to change.
> 
> This is because all ODM/OEMs except QCA bothered to write
> the correct MAC address for the ath10k wifi into the
> calibration data.
I don't think that's a strong enough reason to further propagate the
messy calibration data patching.
How about checking the sysfs device path in the hotplug script instead
to make sure we're changing the MAC for the right wifi device?

- Felix
Ben Greear Nov. 14, 2018, 7:39 p.m. UTC | #2
On 11/01/2018 03:18 AM, Felix Fietkau wrote:
> On 2018-10-28 17:39, Christian Lamparter wrote:
>> Ben Greear reported in his patch:
>> |Subject: netgear r7800: Fix mac address of radios.
>> |
>> |Reloading the driver causes the phyX to change, and that
>> |caused the MAC address to change.
>>
>> This is because all ODM/OEMs except QCA bothered to write
>> the correct MAC address for the ath10k wifi into the
>> calibration data.
> I don't think that's a strong enough reason to further propagate the
> messy calibration data patching.
> How about checking the sysfs device path in the hotplug script instead
> to make sure we're changing the MAC for the right wifi device?

Would this mean that the NIC is loaded with one (potentially bogus)
MAC, and then hotplug would very soon after set the proper MAC?

If so, that is liable to mess up stock ath10k firmware since it will not
properly calculate its rx-bssid mask.

Thanks,
Ben
Felix Fietkau Nov. 14, 2018, 7:53 p.m. UTC | #3
On 2018-11-14 20:39, Ben Greear wrote:
> On 11/01/2018 03:18 AM, Felix Fietkau wrote:
>> On 2018-10-28 17:39, Christian Lamparter wrote:
>>> Ben Greear reported in his patch:
>>> |Subject: netgear r7800: Fix mac address of radios.
>>> |
>>> |Reloading the driver causes the phyX to change, and that
>>> |caused the MAC address to change.
>>>
>>> This is because all ODM/OEMs except QCA bothered to write
>>> the correct MAC address for the ath10k wifi into the
>>> calibration data.
>> I don't think that's a strong enough reason to further propagate the
>> messy calibration data patching.
>> How about checking the sysfs device path in the hotplug script instead
>> to make sure we're changing the MAC for the right wifi device?
> 
> Would this mean that the NIC is loaded with one (potentially bogus)
> MAC, and then hotplug would very soon after set the proper MAC?
> 
> If so, that is liable to mess up stock ath10k firmware since it will not
> properly calculate its rx-bssid mask.
To improve MAC address handling, we should probably call
pdev_set_base_macaddr_cmdid before bringing up the first vif and use the
first vif MAC address there.

- Felix
Ben Greear Nov. 14, 2018, 7:57 p.m. UTC | #4
On 11/14/2018 11:53 AM, Felix Fietkau wrote:
> On 2018-11-14 20:39, Ben Greear wrote:
>> On 11/01/2018 03:18 AM, Felix Fietkau wrote:
>>> On 2018-10-28 17:39, Christian Lamparter wrote:
>>>> Ben Greear reported in his patch:
>>>> |Subject: netgear r7800: Fix mac address of radios.
>>>> |
>>>> |Reloading the driver causes the phyX to change, and that
>>>> |caused the MAC address to change.
>>>>
>>>> This is because all ODM/OEMs except QCA bothered to write
>>>> the correct MAC address for the ath10k wifi into the
>>>> calibration data.
>>> I don't think that's a strong enough reason to further propagate the
>>> messy calibration data patching.
>>> How about checking the sysfs device path in the hotplug script instead
>>> to make sure we're changing the MAC for the right wifi device?
>>
>> Would this mean that the NIC is loaded with one (potentially bogus)
>> MAC, and then hotplug would very soon after set the proper MAC?
>>
>> If so, that is liable to mess up stock ath10k firmware since it will not
>> properly calculate its rx-bssid mask.
> To improve MAC address handling, we should probably call
> pdev_set_base_macaddr_cmdid before bringing up the first vif and use the
> first vif MAC address there.

That might help in general, though not sure exactly how well that is implemented
in stock QCA firmware..  My ath10k-ct doesn't need that to do proper bssid-mask,
and I'd still like the 'phy' to have the correct MAC address, so I still think MAC
should be proper from the very first if at all possible.

I tried an earlier version of Christian's patch and it works well for me on the r7800.

Thanks,
Ben
Mathias Kresin Dec. 6, 2018, 8:24 p.m. UTC | #5
28/10/2018 17:39, Christian Lamparter:
> Ben Greear reported in his patch:
> |Subject: netgear r7800: Fix mac address of radios.
> |
> |Reloading the driver causes the phyX to change, and that
> |caused the MAC address to change.
> 
> This is because all ODM/OEMs except QCA bothered to write
> the correct MAC address for the ath10k wifi into the
> calibration data.
> 
> This patch copies over the MAC patching helper functions from ipq40xx's
> target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
> file and converts all the devices to patch the correct MACs into the
> extracted calibration data before it gets sent to the driver, which sets
> up the device with the correct MAC address. It also removes the
> 10_fix_wifi_mac file as it has served its purpose.
> 
> Please note the C2600: There is conflicting information on what
> the offset for the second wifi is supposed to be. This patch uses
> what was specified in 10_fix_wifi_mac.
> 
> Reported-by: Ben Greear <greearb@candelatech.com>
> Signed-off-by: Christian Lamparter <chunkeey@gmail.com>

Hey Felix,

as long as you don't strongly disagree, I would like to pick this patch.

I don't consider the calibration data patching as messy, as it is the 
place where the mac address is expected but unfortunately not correct set.

Beside the issues mentioned by Ben, I really don't like to split the 
wireless calibration data and wireless mac address handling across 
multiple files if it can be done at a single place.

Mathias

> ---
>   .../etc/hotplug.d/firmware/11-ath10k-caldata  | 64 +++++++++++++++++--
>   .../etc/hotplug.d/ieee80211/10_fix_wifi_mac   | 37 -----------
>   2 files changed, 57 insertions(+), 44 deletions(-)
>   delete mode 100644 target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
> 
> diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
> index fa49c250f0..1d070603f2 100644
> --- a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
> +++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
> @@ -1,5 +1,21 @@
>   #!/bin/sh
>   
> +# xor multiple hex values of the same length
> +xor() {
> +	local val
> +	local ret="0x$1"
> +	local retlen=${#1}
> +
> +	shift
> +	while [ -n "$1" ]; do
> +		val="0x$1"
> +		ret=$((ret ^ val))
> +		shift
> +	done
> +
> +	printf "%0${retlen}x" "$ret"
> +}
> +
>   ath10kcal_die() {
>   	echo "ath10cal: " "$*"
>   	exit 1
> @@ -36,6 +52,29 @@ ath10kcal_patch_mac() {
>   	macaddr_2bin $mac | dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=6 count=6
>   }
>   
> +ath10kcal_patch_mac_crc() {
> +	local mac=$1
> +	local mac_offset=6
> +	local chksum_offset=2
> +	local xor_mac
> +	local xor_fw_mac
> +	local xor_fw_chksum
> +
> +	xor_fw_mac=$(hexdump -v -n 6 -s $mac_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE)
> +	xor_fw_mac="${xor_fw_mac:0:4} ${xor_fw_mac:4:4} ${xor_fw_mac:8:4}"
> +
> +	ath10kcal_patch_mac "$mac" && {
> +		xor_mac=${mac//:/}
> +		xor_mac="${xor_mac:0:4} ${xor_mac:4:4} ${xor_mac:8:4}"
> +
> +		xor_fw_chksum=$(hexdump -v -n 2 -s $chksum_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE)
> +		xor_fw_chksum=$(xor $xor_fw_chksum $xor_fw_mac $xor_mac)
> +
> +		printf "%b" "\x${xor_fw_chksum:0:2}\x${xor_fw_chksum:2:2}" | \
> +			dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=$chksum_offset count=2
> +	}
> +}
> +
>   [ -e /lib/firmware/$FIRMWARE ] && exit 0
>   
>   . /lib/functions.sh
> @@ -43,53 +82,64 @@ ath10kcal_patch_mac() {
>   
>   board=$(board_name)
>   
> -
>   case "$FIRMWARE" in
>   "ath10k/pre-cal-pci-0000:01:00.0.bin")
>   	case $board in
>   	linksys,ea8500)
> -		hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr)
>   		ath10kcal_extract "art" 4096 12064
> +		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +1)
> +		;;
> +	nec,wg2600hp)
> +		ath10kcal_extract "ART" 4096 12064
> +		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary PRODUCTDATA 12) +1)
>   		;;
>   	netgear,d7800 |\
>   	netgear,r7500v2 |\
>   	netgear,r7800)
>   		ath10kcal_extract "art" 4096 12064
> +		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary art 6) +1)
>   		;;
>   	tplink,c2600)
>   		ath10kcal_extract "radio" 4096 12064
> -# 		ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -1)
> +		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary default-mac 8) -1)
>   		;;
> -	nec,wg2600hp |\
>   	tplink,vr2600v)
>   		ath10kcal_extract "ART" 4096 12064
> +		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary default-mac 0) -1)
>   		;;
>   	zyxel,nbg6817)
>   		ath10kcal_extract "0:ART" 4096 12064
> +		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) +1)
>   		;;
>   	esac
>   	;;
>   "ath10k/pre-cal-pci-0001:01:00.0.bin")
>   	case $board in
>   	linksys,ea8500)
> -		hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr)
>   		ath10kcal_extract "art" 20480 12064
> +		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +2)
> +		;;
> +	nec,wg2600hp)
> +		ath10kcal_extract "ART" 20480 12064
> +		ath10kcal_patch_mac_crc $(mtd_get_mac_binary PRODUCTDATA 12)
>   		;;
>   	netgear,d7800 |\
>   	netgear,r7500v2 |\
>   	netgear,r7800)
>   		ath10kcal_extract "art" 20480 12064
> +		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary art 6) +2)
>   		;;
>   	tplink,c2600)
>   		ath10kcal_extract "radio" 20480 12064
> -# 		ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -2)
> +		ath10kcal_patch_mac_crc $(mtd_get_mac_binary default-mac 8)
>   		;;
> -	nec,wg2600hp |\
>   	tplink,vr2600v)
>   		ath10kcal_extract "ART" 20480 12064
> +		ath10kcal_patch_mac_crc $(mtd_get_mac_binary default-mac 0)
>   		;;
>   	zyxel,nbg6817)
>   		ath10kcal_extract "0:ART" 20480 12064
> +		ath10kcal_patch_mac_crc $(mtd_get_mac_ascii 0:APPSBLENV ethaddr)
>   		;;
>   	esac
>   	;;
> diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
> deleted file mode 100644
> index afa425f075..0000000000
> --- a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
> +++ /dev/null
> @@ -1,37 +0,0 @@
> -#!/bin/ash
> -
> -[ "$ACTION" == "add" ] || exit 0
> -
> -PHYNBR=${DEVPATH##*/phy}
> -
> -[ -n $PHYNBR ] || exit 0
> -
> -. /lib/functions.sh
> -. /lib/functions/system.sh
> -
> -board=$(board_name)
> -
> -case "$board" in
> -	linksys,ea8500)
> -		echo $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress
> -		;;
> -	nec,wg2600hp)
> -		echo $(macaddr_add $(mtd_get_mac_binary PRODUCTDATA 12) $((1 - $PHYNBR)) ) > /sys${DEVPATH}/macaddress
> -		;;
> -	netgear,d7800 |\
> -	netgear,r7500v2 |\
> -	netgear,r7800)
> -		echo $(macaddr_add $(mtd_get_mac_binary art 6)  $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress
> -		;;
> -	tplink,c2600)
> -		echo $(macaddr_add $(mtd_get_mac_binary default-mac 8)  $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress
> -		;;
> -	tplink,vr2600v)
> -		echo $(macaddr_add $(mtd_get_mac_binary default-mac 0)  $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress
> -		;;
> -	zyxel,nbg6817)
> -		echo $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) $((1 - $PHYNBR)) ) > /sys${DEVPATH}/macaddress
> -		;;
> -	*)
> -		;;
> -esac
>
Chuanhong Guo Dec. 7, 2018, 8:26 a.m. UTC | #6
Hi!
On Mon, Oct 29, 2018 at 12:40 AM Christian Lamparter <chunkeey@gmail.com> wrote:
>
> Ben Greear reported in his patch:
> |Subject: netgear r7800: Fix mac address of radios.
> |
> |Reloading the driver causes the phyX to change, and that
> |caused the MAC address to change.
>
> This is because all ODM/OEMs except QCA bothered to write
> the correct MAC address for the ath10k wifi into the
> calibration data.
>
> This patch copies over the MAC patching helper functions from ipq40xx's
> target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
> file and converts all the devices to patch the correct MACs into the
> extracted calibration data before it gets sent to the driver, which sets
> up the device with the correct MAC address. It also removes the
> 10_fix_wifi_mac file as it has served its purpose.
>
> Please note the C2600: There is conflicting information on what
> the offset for the second wifi is supposed to be. This patch uses
> what was specified in 10_fix_wifi_mac.
>
> Reported-by: Ben Greear <greearb@candelatech.com>
> Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
> ---
>  .../etc/hotplug.d/firmware/11-ath10k-caldata  | 64 +++++++++++++++++--
>  .../etc/hotplug.d/ieee80211/10_fix_wifi_mac   | 37 -----------
>  2 files changed, 57 insertions(+), 44 deletions(-)
>  delete mode 100644 target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
>
> diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
> index fa49c250f0..1d070603f2 100644
> --- a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
> +++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
> @@ -1,5 +1,21 @@
>  #!/bin/sh
>
> +# xor multiple hex values of the same length
> +xor() {
> +       local val
> +       local ret="0x$1"
> +       local retlen=${#1}
> +
> +       shift
> +       while [ -n "$1" ]; do
> +               val="0x$1"
> +               ret=$((ret ^ val))
> +               shift
> +       done
> +
> +       printf "%0${retlen}x" "$ret"
> +}
> +
>  ath10kcal_die() {
>         echo "ath10cal: " "$*"
>         exit 1
> @@ -36,6 +52,29 @@ ath10kcal_patch_mac() {
>         macaddr_2bin $mac | dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=6 count=6
>  }
>
> +ath10kcal_patch_mac_crc() {
> +       local mac=$1
> +       local mac_offset=6
> +       local chksum_offset=2
> +       local xor_mac
> +       local xor_fw_mac
> +       local xor_fw_chksum
> +
> +       xor_fw_mac=$(hexdump -v -n 6 -s $mac_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE)
> +       xor_fw_mac="${xor_fw_mac:0:4} ${xor_fw_mac:4:4} ${xor_fw_mac:8:4}"
> +
> +       ath10kcal_patch_mac "$mac" && {
> +               xor_mac=${mac//:/}
> +               xor_mac="${xor_mac:0:4} ${xor_mac:4:4} ${xor_mac:8:4}"
> +
> +               xor_fw_chksum=$(hexdump -v -n 2 -s $chksum_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE)
> +               xor_fw_chksum=$(xor $xor_fw_chksum $xor_fw_mac $xor_mac)
> +
> +               printf "%b" "\x${xor_fw_chksum:0:2}\x${xor_fw_chksum:2:2}" | \
> +                       dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=$chksum_offset count=2
> +       }
> +}
> +
I think we should replace the ath10kcal_patch_mac directly instead of
introducing another function.
All ath10k calibration data have a checksum at 0x2.
ath10kcal_patch_mac works for QCA9880/QCA9882 only because the ath10k
firmware for these two chips doesn't check the checksum value. (QCA
proprietary driver checks this and refuses to use caldata with
incorrect checksum.)
>  [ -e /lib/firmware/$FIRMWARE ] && exit 0
>
>  . /lib/functions.sh
> @@ -43,53 +82,64 @@ ath10kcal_patch_mac() {
>
>  board=$(board_name)
>
> -
>  case "$FIRMWARE" in
>  "ath10k/pre-cal-pci-0000:01:00.0.bin")
>         case $board in
>         linksys,ea8500)
> -               hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr)
>                 ath10kcal_extract "art" 4096 12064
> +               ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +1)
> +               ;;
> +       nec,wg2600hp)
> +               ath10kcal_extract "ART" 4096 12064
> +               ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary PRODUCTDATA 12) +1)
>                 ;;
>         netgear,d7800 |\
>         netgear,r7500v2 |\
>         netgear,r7800)
>                 ath10kcal_extract "art" 4096 12064
> +               ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary art 6) +1)
>                 ;;
>         tplink,c2600)
>                 ath10kcal_extract "radio" 4096 12064
> -#              ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -1)
> +               ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary default-mac 8) -1)
>                 ;;
> -       nec,wg2600hp |\
>         tplink,vr2600v)
>                 ath10kcal_extract "ART" 4096 12064
> +               ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary default-mac 0) -1)
>                 ;;
>         zyxel,nbg6817)
>                 ath10kcal_extract "0:ART" 4096 12064
> +               ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) +1)
>                 ;;
>         esac
>         ;;
>  "ath10k/pre-cal-pci-0001:01:00.0.bin")
>         case $board in
>         linksys,ea8500)
> -               hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr)
>                 ath10kcal_extract "art" 20480 12064
> +               ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +2)
> +               ;;
> +       nec,wg2600hp)
> +               ath10kcal_extract "ART" 20480 12064
> +               ath10kcal_patch_mac_crc $(mtd_get_mac_binary PRODUCTDATA 12)
>                 ;;
>         netgear,d7800 |\
>         netgear,r7500v2 |\
>         netgear,r7800)
>                 ath10kcal_extract "art" 20480 12064
> +               ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary art 6) +2)
>                 ;;
>         tplink,c2600)
>                 ath10kcal_extract "radio" 20480 12064
> -#              ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -2)
> +               ath10kcal_patch_mac_crc $(mtd_get_mac_binary default-mac 8)
>                 ;;
> -       nec,wg2600hp |\
>         tplink,vr2600v)
>                 ath10kcal_extract "ART" 20480 12064
> +               ath10kcal_patch_mac_crc $(mtd_get_mac_binary default-mac 0)
>                 ;;
>         zyxel,nbg6817)
>                 ath10kcal_extract "0:ART" 20480 12064
> +               ath10kcal_patch_mac_crc $(mtd_get_mac_ascii 0:APPSBLENV ethaddr)
>                 ;;
>         esac
>         ;;
> diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
> deleted file mode 100644
> index afa425f075..0000000000
> --- a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
> +++ /dev/null
> @@ -1,37 +0,0 @@
> -#!/bin/ash
> -
> -[ "$ACTION" == "add" ] || exit 0
> -
> -PHYNBR=${DEVPATH##*/phy}
> -
> -[ -n $PHYNBR ] || exit 0
> -
> -. /lib/functions.sh
> -. /lib/functions/system.sh
> -
> -board=$(board_name)
> -
> -case "$board" in
> -       linksys,ea8500)
> -               echo $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress
> -               ;;
> -       nec,wg2600hp)
> -               echo $(macaddr_add $(mtd_get_mac_binary PRODUCTDATA 12) $((1 - $PHYNBR)) ) > /sys${DEVPATH}/macaddress
> -               ;;
> -       netgear,d7800 |\
> -       netgear,r7500v2 |\
> -       netgear,r7800)
> -               echo $(macaddr_add $(mtd_get_mac_binary art 6)  $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress
> -               ;;
> -       tplink,c2600)
> -               echo $(macaddr_add $(mtd_get_mac_binary default-mac 8)  $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress
> -               ;;
> -       tplink,vr2600v)
> -               echo $(macaddr_add $(mtd_get_mac_binary default-mac 0)  $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress
> -               ;;
> -       zyxel,nbg6817)
> -               echo $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) $((1 - $PHYNBR)) ) > /sys${DEVPATH}/macaddress
> -               ;;
> -       *)
> -               ;;
> -esac
> --
> 2.19.1
>
>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel
Christian Lamparter Dec. 15, 2018, 8:10 p.m. UTC | #7
On Wednesday, November 14, 2018 8:39:22 PM CET Ben Greear wrote:
> On 11/01/2018 03:18 AM, Felix Fietkau wrote:
> > On 2018-10-28 17:39, Christian Lamparter wrote:
> >> Ben Greear reported in his patch:
> >> |Subject: netgear r7800: Fix mac address of radios.
> >> |
> >> |Reloading the driver causes the phyX to change, and that
> >> |caused the MAC address to change.
> >>
> >> This is because all ODM/OEMs except QCA bothered to write
> >> the correct MAC address for the ath10k wifi into the
> >> calibration data.
> > I don't think that's a strong enough reason to further propagate the
> > messy calibration data patching.
> > How about checking the sysfs device path in the hotplug script instead
> > to make sure we're changing the MAC for the right wifi device?
> 
> Would this mean that the NIC is loaded with one (potentially bogus)
> MAC, and then hotplug would very soon after set the proper MAC?
> 
> If so, that is liable to mess up stock ath10k firmware since it will not
> properly calculate its rx-bssid mask.

Let's test it then.

Ben, Felix: I've prepared a big, one in all, test patch for the R7800 -
that if viable will be split up, upstreamed and merged accordingly.

This patch contains:

0. ath10k and ath10k-ct fixes that implement Felix request to 
   "call pdev_set_base_macaddr_cmdid before bringing up the first vif".
   This is in the "976-ath10k-implement-set-base-macaddr" patch.
   (Note: the ath10k driver had no support code for this function, nor
   does it mention what the data the pdev_set_base_macaddr_cmdid takes.
   I assume it's just 6-bytes for the base MAC.) 

   Ben: Can you please comment if this is all right, or if something
        needs to be changed? 

1. 998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
   This is an upstream patch

2. 950-call-of_get_mac_address-from-device.patch
   A hack that makes it work. This could be a point of conflict.

3. R7800 dts changes
   I hope they are correct enough. I don't have the hardware to test
   it.

4. (userspace code).

In the mean time, because this is so much new, experimental stuff. I'll go
ahead with the ugly firmware patching for now until this is ready for
prime time.

Regards,
Christian

---
commit ef013d0f30d406a5378d21832562c1ffc0f0f29f
Author: Christian Lamparter <chunkeey@gmail.com>
Date:   Sat Dec 15 10:56:14 2018 +0100

    ipq806x: R7800: mtd-mac-address test

diff --git a/package/kernel/ath10k-ct/patches/976-ath10k-implement-set-base-macaddr.patch b/package/kernel/ath10k-ct/patches/976-ath10k-implement-set-base-macaddr.patch
new file mode 100644
index 0000000000..46dba87a93
--- /dev/null
+++ b/package/kernel/ath10k-ct/patches/976-ath10k-implement-set-base-macaddr.patch
@@ -0,0 +1,172 @@
+--- a/ath10k-4.16/core.c
++++ b/ath10k-4.16/core.c
+@@ -2621,6 +2621,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
+ 		goto err_hif_stop;
+ 	}
+ 
++	status = ath10k_wmi_pdev_set_base_macaddr(ar, ar->mac_addr);
++	if (status) {
++		ath10k_err(ar,
++			   "failed to set base mac address: %d\n", status);
++		goto err_hif_stop;
++	}
++
+ 	/* Some firmware revisions do not properly set up hardware rx filter
+ 	 * registers.
+ 	 *
+--- a/ath10k-4.16/wmi-ops.h
++++ b/ath10k-4.16/wmi-ops.h
+@@ -64,6 +64,8 @@ struct wmi_ops {
+ 
+ 	enum wmi_txbf_conf (*get_txbf_conf_scheme)(struct ath10k *ar);
+ 
++	struct sk_buff *(*gen_pdev_set_base_macaddr)(struct ath10k *ar,
++						     const u8 macaddr[ETH_ALEN]);
+ 	struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
+ 	struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
+ 	struct sk_buff *(*gen_pdev_set_rd)(struct ath10k *ar, u16 rd, u16 rd2g,
+@@ -503,6 +505,22 @@ ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
+ 				   ar->wmi.cmd->pdev_set_regdomain_cmdid);
+ }
+ 
++static inline int
++ath10k_wmi_pdev_set_base_macaddr(struct ath10k *ar, const u8 macaddr[ETH_ALEN])
++{
++	struct sk_buff *skb;
++
++	if (!ar->wmi.ops->gen_pdev_set_base_macaddr)
++		return -EOPNOTSUPP;
++
++	skb = ar->wmi.ops->gen_pdev_set_base_macaddr(ar, macaddr);
++	if (IS_ERR(skb))
++		return PTR_ERR(skb);
++
++	return ath10k_wmi_cmd_send(ar, skb,
++				   ar->wmi.cmd->pdev_set_base_macaddr_cmdid);
++}
++
+ static inline int
+ ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
+ {
+--- a/ath10k-4.16/wmi-tlv.c
++++ b/ath10k-4.16/wmi-tlv.c
+@@ -2228,6 +2228,29 @@ ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
+ 	return skb;
+ }
+ 
++static struct sk_buff *
++ath10k_wmi_tlv_op_gen_pdev_set_base_macaddr(struct ath10k *ar,
++					    const u8 addr[ETH_ALEN])
++{
++	struct wmi_pdev_set_base_macaddr_cmd *cmd;
++	struct wmi_tlv *tlv;
++	struct sk_buff *skb;
++
++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
++	if (!skb)
++		return ERR_PTR(-ENOMEM);
++
++	tlv = (void *)skb->data;
++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_BASE_MACADDR_CMD);
++	tlv->len = __cpu_to_le16(sizeof(*cmd));
++	cmd = (void *)tlv->value;
++	ether_addr_copy(cmd->mac_addr.addr, addr);
++
++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set base macaddr\n");
++	return skb;
++}
++
++
+ static struct sk_buff *
+ ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
+ 				  const u8 peer_addr[ETH_ALEN])
+@@ -4112,6 +4135,8 @@ static const struct wmi_ops wmi_tlv_ops = {
+ 	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr =
++			ath10k_wmi_tlv_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_tlv_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
+--- a/ath10k-4.16/wmi.c
++++ b/ath10k-4.16/wmi.c
+@@ -6012,6 +6012,25 @@ int ath10k_wmi_connect(struct ath10k *ar
+ }
+ 
+ static struct sk_buff *
++ath10k_wmi_op_gen_pdev_set_base_macaddr(struct ath10k *ar,
++					const u8 macaddr[ETH_ALEN])
++{
++	struct wmi_pdev_set_base_macaddr_cmd *cmd;
++	struct sk_buff *skb;
++
++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
++	if (!skb)
++		return ERR_PTR(-ENOMEM);
++
++	cmd = (struct wmi_pdev_set_base_macaddr_cmd *)skb->data;
++	ether_addr_copy(cmd->mac_addr.addr, macaddr);
++
++	ath10k_dbg(ar, ATH10K_DBG_WMI,
++		   "wmi pdev basemac %pM\n", macaddr);
++	return skb;
++}
++
++static struct sk_buff *
+ ath10k_wmi_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
+ 			      u16 ctl2g, u16 ctl5g,
+ 			      enum wmi_dfs_region dfs_reg)
+@@ -8919,6 +8938,7 @@ static const struct wmi_ops wmi_ops = {
+ 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
+@@ -8996,6 +9016,7 @@ static const struct wmi_ops wmi_10_1_ops
+ 	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
+ 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+ 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
+ 	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
+ 	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
+@@ -9052,6 +9073,7 @@ static const struct wmi_ops wmi_10_2_ops
+ 	.pull_fw_stats = ath10k_wmi_10_2_op_pull_fw_stats,
+ 	.gen_init = ath10k_wmi_10_2_op_gen_init,
+ 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	/* .gen_pdev_get_temperature not implemented */
+ 
+ 	/* shared with 10.1 */
+@@ -9123,6 +9145,7 @@ static const struct wmi_ops wmi_10_2_4_o
+ 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
+ 	.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
+ 	.gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 
+ 	/* shared with 10.1 */
+ 	.map_svc = wmi_10x_svc_map,
+@@ -9252,6 +9275,7 @@ static const struct wmi_ops wmi_10_4_ops
+ 	.ext_resource_config = ath10k_wmi_10_4_ext_resource_config,
+ 	.gen_update_fw_tdls_state = ath10k_wmi_10_4_gen_update_fw_tdls_state,
+ 	.gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 
+ 	/* shared with 10.2 */
+ 	.pull_echo_ev = ath10k_wmi_op_pull_echo_ev,
+--- a/ath10k-4.16/wmi.h
++++ b/ath10k-4.16/wmi.h
+@@ -4067,6 +4067,10 @@ struct wmi_pdev_set_param_cmd {
+ 	__le32 param_value;
+ } __packed;
+ 
++struct wmi_pdev_set_base_macaddr_cmd {
++	struct wmi_mac_addr mac_addr;
++} __packed;
++
+ /* valid period is 1 ~ 60000ms, unit in millisecond */
+ #define WMI_PDEV_PARAM_CAL_PERIOD_MAX 60000
+ 
diff --git a/package/kernel/ath10k-ct/patches/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch b/package/kernel/ath10k-ct/patches/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
new file mode 100644
index 0000000000..162536d6a4
--- /dev/null
+++ b/package/kernel/ath10k-ct/patches/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
@@ -0,0 +1,50 @@
+From 9d5804662ce1f9bdde0a14c3c40940acbbf09538 Mon Sep 17 00:00:00 2001
+From: Brian Norris <briannorris@chromium.org>
+Date: Tue, 28 Aug 2018 19:48:17 +0300
+Subject: [PATCH] ath10k: retrieve MAC address from system firmware if provided
+
+Devices may provide their own MAC address via system firmware (e.g.,
+device tree), especially in the case where the device doesn't have a
+useful EEPROM on which to store its MAC address (e.g., for integrated
+Wifi).
+
+Use the generic device helper to retrieve the MAC address, and (if
+present) honor it above the MAC address advertised by the card.
+
+Signed-off-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+--- a/ath10k-4.16/core.c
++++ b/ath10k-4.16/core.c
+@@ -19,6 +19,7 @@
+ #include <linux/module.h>
+ #include <linux/firmware.h>
+ #include <linux/of.h>
++#include <linux/property.h>
+ #include <linux/dmi.h>
+ #include <linux/ctype.h>
+ #include <asm/byteorder.h>
+@@ -2617,6 +2618,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
+ 		ath10k_debug_print_board_info(ar);
+ 	}
+ 
++	device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr));
++
+ 	ret = ath10k_core_init_firmware_features(ar);
+ 	if (ret) {
+ 		ath10k_err(ar, "fatal problem with firmware features: %d\n",
+--- a/ath10k-4.16/wmi.c
++++ b/ath10k-4.16/wmi.c
+@@ -5455,7 +5455,8 @@ int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
+ 		   arg.mac_addr,
+ 		   __le32_to_cpu(arg.status));
+ 
+-	ether_addr_copy(ar->mac_addr, arg.mac_addr);
++	if (is_zero_ether_addr(ar->mac_addr))
++		ether_addr_copy(ar->mac_addr, arg.mac_addr);
+ 	complete(&ar->wmi.unified_ready);
+ 	return 0;
+ }
+-- 
+2.20.0
+
diff --git a/package/kernel/mac80211/patches/ath/977-ath10k-implement-set-base-macaddr.patch b/package/kernel/mac80211/patches/ath/977-ath10k-implement-set-base-macaddr.patch
new file mode 100644
index 0000000000..864972090f
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/977-ath10k-implement-set-base-macaddr.patch
@@ -0,0 +1,182 @@
+diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
+index 22cbe9a2e646..33c767b903bc 100644
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -2621,6 +2621,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
+ 		goto err_hif_stop;
+ 	}
+ 
++	status = ath10k_wmi_pdev_set_base_macaddr(ar, ar->mac_addr);
++	if (status) {
++		ath10k_err(ar,
++			   "failed to set base mac address: %d\n", status);
++		goto err_hif_stop;
++	}
++
+ 	/* Some firmware revisions do not properly set up hardware rx filter
+ 	 * registers.
+ 	 *
+diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
+index 7978a7783f90..6c87b35cde4e 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
+@@ -64,6 +64,8 @@ struct wmi_ops {
+ 
+ 	enum wmi_txbf_conf (*get_txbf_conf_scheme)(struct ath10k *ar);
+ 
++	struct sk_buff *(*gen_pdev_set_base_macaddr)(struct ath10k *ar,
++						     const u8 macaddr[ETH_ALEN]);
+ 	struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
+ 	struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
+ 	struct sk_buff *(*gen_pdev_set_rd)(struct ath10k *ar, u16 rd, u16 rd2g,
+@@ -503,6 +505,22 @@ ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
+ 				   ar->wmi.cmd->pdev_set_regdomain_cmdid);
+ }
+ 
++static inline int
++ath10k_wmi_pdev_set_base_macaddr(struct ath10k *ar, const u8 macaddr[ETH_ALEN])
++{
++	struct sk_buff *skb;
++
++	if (!ar->wmi.ops->gen_pdev_set_base_macaddr)
++		return -EOPNOTSUPP;
++
++	skb = ar->wmi.ops->gen_pdev_set_base_macaddr(ar, macaddr);
++	if (IS_ERR(skb))
++		return PTR_ERR(skb);
++
++	return ath10k_wmi_cmd_send(ar, skb,
++				   ar->wmi.cmd->pdev_set_base_macaddr_cmdid);
++}
++
+ static inline int
+ ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
+ {
+diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+index ad4114a88170..60beb8283e30 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+@@ -2228,6 +2228,29 @@ ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
+ 	return skb;
+ }
+ 
++static struct sk_buff *
++ath10k_wmi_tlv_op_gen_pdev_set_base_macaddr(struct ath10k *ar,
++					    const u8 addr[ETH_ALEN])
++{
++	struct wmi_pdev_set_base_macaddr_cmd *cmd;
++	struct wmi_tlv *tlv;
++	struct sk_buff *skb;
++
++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
++	if (!skb)
++		return ERR_PTR(-ENOMEM);
++
++	tlv = (void *)skb->data;
++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_BASE_MACADDR_CMD);
++	tlv->len = __cpu_to_le16(sizeof(*cmd));
++	cmd = (void *)tlv->value;
++	ether_addr_copy(cmd->mac_addr.addr, addr);
++
++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set base macaddr\n");
++	return skb;
++}
++
++
+ static struct sk_buff *
+ ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
+ 				  const u8 peer_addr[ETH_ALEN])
+@@ -4112,6 +4135,8 @@ static const struct wmi_ops wmi_tlv_ops = {
+ 	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr =
++			ath10k_wmi_tlv_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_tlv_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
+diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
+index 659513bf4ddc..d1a021e1c784 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -6234,6 +6234,25 @@ int ath10k_wmi_connect(struct ath10k *ar)
+ 	return 0;
+ }
+ 
++static struct sk_buff *
++ath10k_wmi_op_gen_pdev_set_base_macaddr(struct ath10k *ar,
++					const u8 macaddr[ETH_ALEN])
++{
++	struct wmi_pdev_set_base_macaddr_cmd *cmd;
++	struct sk_buff *skb;
++
++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
++	if (!skb)
++		return ERR_PTR(-ENOMEM);
++
++	cmd = (struct wmi_pdev_set_base_macaddr_cmd *)skb->data;
++	ether_addr_copy(cmd->mac_addr.addr, macaddr);
++
++	ath10k_dbg(ar, ATH10K_DBG_WMI,
++		   "wmi pdev basemac %pM\n", macaddr);
++	return skb;
++}
++
+ static struct sk_buff *
+ ath10k_wmi_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
+ 			      u16 ctl2g, u16 ctl5g,
+@@ -8861,6 +8880,7 @@ static const struct wmi_ops wmi_ops = {
+ 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
+@@ -8917,6 +8937,7 @@ static const struct wmi_ops wmi_10_1_ops = {
+ 	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
+ 	.gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
+ 	.gen_peer_assoc = ath10k_wmi_10_1_op_gen_peer_assoc,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	/* .gen_pdev_get_temperature not implemented */
+ 
+ 	/* shared with main branch */
+@@ -8983,6 +9004,7 @@ static const struct wmi_ops wmi_10_2_ops = {
+ 	.pull_fw_stats = ath10k_wmi_10_2_op_pull_fw_stats,
+ 	.gen_init = ath10k_wmi_10_2_op_gen_init,
+ 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	/* .gen_pdev_get_temperature not implemented */
+ 
+ 	/* shared with 10.1 */
+@@ -9052,6 +9074,7 @@ static const struct wmi_ops wmi_10_2_4_ops = {
+ 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
+ 	.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
+ 	.gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 
+ 	/* shared with 10.1 */
+ 	.map_svc = wmi_10x_svc_map,
+@@ -9141,6 +9164,7 @@ static const struct wmi_ops wmi_10_4_ops = {
+ 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_10_4_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
+diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
+index 58e33ab9e0e9..e0cc0c3a384f 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi.h
++++ b/drivers/net/wireless/ath/ath10k/wmi.h
+@@ -4067,6 +4067,10 @@ struct wmi_pdev_set_param_cmd {
+ 	__le32 param_value;
+ } __packed;
+ 
++struct wmi_pdev_set_base_macaddr_cmd {
++	struct wmi_mac_addr mac_addr;
++} __packed;
++
+ /* valid period is 1 ~ 60000ms, unit in millisecond */
+ #define WMI_PDEV_PARAM_CAL_PERIOD_MAX 60000
+ 
diff --git a/package/kernel/mac80211/patches/ath/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch b/package/kernel/mac80211/patches/ath/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
new file mode 100644
index 0000000000..d4f9c64a44
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
@@ -0,0 +1,58 @@
+From 9d5804662ce1f9bdde0a14c3c40940acbbf09538 Mon Sep 17 00:00:00 2001
+From: Brian Norris <briannorris@chromium.org>
+Date: Tue, 28 Aug 2018 19:48:17 +0300
+Subject: [PATCH] ath10k: retrieve MAC address from system firmware if provided
+
+Devices may provide their own MAC address via system firmware (e.g.,
+device tree), especially in the case where the device doesn't have a
+useful EEPROM on which to store its MAC address (e.g., for integrated
+Wifi).
+
+Use the generic device helper to retrieve the MAC address, and (if
+present) honor it above the MAC address advertised by the card.
+
+Signed-off-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/ath/ath10k/core.c | 3 +++
+ drivers/net/wireless/ath/ath10k/wmi.c  | 3 ++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
+index ebc213884a9a..f5f71c02fc2b 100644
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -19,6 +19,7 @@
+ #include <linux/module.h>
+ #include <linux/firmware.h>
+ #include <linux/of.h>
++#include <linux/property.h>
+ #include <linux/dmi.h>
+ #include <linux/ctype.h>
+ #include <asm/byteorder.h>
+@@ -2617,6 +2618,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
+ 		ath10k_debug_print_board_info(ar);
+ 	}
+ 
++	device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr));
++
+ 	ret = ath10k_core_init_firmware_features(ar);
+ 	if (ret) {
+ 		ath10k_err(ar, "fatal problem with firmware features: %d\n",
+diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
+index 40ce0e4006bc..212005cd0646 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -5455,7 +5455,8 @@ int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
+ 		   arg.mac_addr,
+ 		   __le32_to_cpu(arg.status));
+ 
+-	ether_addr_copy(ar->mac_addr, arg.mac_addr);
++	if (is_zero_ether_addr(ar->mac_addr))
++		ether_addr_copy(ar->mac_addr, arg.mac_addr);
+ 	complete(&ar->wmi.unified_ready);
+ 	return 0;
+ }
+-- 
+2.20.0
+
diff --git a/target/linux/generic/hack-4.14/950-call-of_get_mac_address-from-device.patch b/target/linux/generic/hack-4.14/950-call-of_get_mac_address-from-device.patch
new file mode 100644
index 0000000000..7e78ceea64
--- /dev/null
+++ b/target/linux/generic/hack-4.14/950-call-of_get_mac_address-from-device.patch
@@ -0,0 +1,23 @@
+--- a/drivers/base/property.c	2018-11-21 09:24:18.000000000 +0100
++++ b/drivers/base/property.c	2018-12-15 13:59:16.894896732 +0100
+@@ -19,6 +19,7 @@
+ #include <linux/property.h>
+ #include <linux/etherdevice.h>
+ #include <linux/phy.h>
++#include <linux/of_net.h>
+ 
+ struct property_set {
+ 	struct device *dev;
+@@ -1186,6 +1187,12 @@ void *device_get_mac_address(struct devi
+ {
+ 	char *res;
+ 
++	res = of_get_mac_address(dev->of_node);
++	if (res && (alen >= ETH_ALEN)) {
++		ether_addr_copy(addr, res);
++		return addr;
++	}
++
+ 	res = device_get_mac_addr(dev, "mac-address", addr, alen);
+ 	if (res)
+ 		return res;
diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
index 8956bbd74a..ad98339540 100644
--- a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
+++ b/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
@@ -19,8 +19,7 @@ case "$board" in
 		echo $(macaddr_add $(mtd_get_mac_binary PRODUCTDATA 12) $((1 - $PHYNBR)) ) > /sys${DEVPATH}/macaddress
 		;;
 	netgear,d7800 |\
-	netgear,r7500v2 |\
-	netgear,r7800)
+	netgear,r7500v2)
 		echo $(macaddr_add $(mtd_get_mac_binary art 6)  $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress
 		;;
 	tplink,c2600)
diff --git a/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8065-r7800.dts b/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8065-r7800.dts
index c4c9287942..614ab15df6 100644
--- a/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8065-r7800.dts
+++ b/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8065-r7800.dts
@@ -255,12 +255,42 @@
 		};
 
 		pcie0: pci@1b500000 {
-			status = "ok";
+			status = "okay";
+
+			bridge@0,0 {
+				reg = <0x00000000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges;
+
+				wifi@1,0 {
+					compatible = "pci168c,0046";
+					reg = <0x00010000 0 0 0 0>;
+
+					mtd-mac-address = <&art 6>;
+					mtd-mac-address-increment = <(1)>;
+				};
+			};
 		};
 
 		pcie1: pci@1b700000 {
-			status = "ok";
+			status = "okay";
 			force_gen1 = <1>;
+
+			bridge@0,0 {
+				reg = <0x00000000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges;
+
+				wifi@1,0 {
+					compatible = "pci168c,0046";
+					reg = <0x00010000 0 0 0 0>;
+
+					mtd-mac-address = <&art 6>;
+					mtd-mac-address-increment = <(2)>;
+				};
+			};
 		};
 
 		nand@1ac00000 {
Christian Lamparter Dec. 17, 2018, 6:05 p.m. UTC | #8
On Saturday, December 15, 2018 9:10:39 PM CET Christian Lamparter wrote:
> On Wednesday, November 14, 2018 8:39:22 PM CET Ben Greear wrote:
> > On 11/01/2018 03:18 AM, Felix Fietkau wrote:
> > > On 2018-10-28 17:39, Christian Lamparter wrote:
> > >> Ben Greear reported in his patch:
> > >> |Subject: netgear r7800: Fix mac address of radios.
> > >> |
> > >> |Reloading the driver causes the phyX to change, and that
> > >> |caused the MAC address to change.
> > >>
> > >> This is because all ODM/OEMs except QCA bothered to write
> > >> the correct MAC address for the ath10k wifi into the
> > >> calibration data.
> > > I don't think that's a strong enough reason to further propagate the
> > > messy calibration data patching.
> > > How about checking the sysfs device path in the hotplug script instead
> > > to make sure we're changing the MAC for the right wifi device?
> > 
> > Would this mean that the NIC is loaded with one (potentially bogus)
> > MAC, and then hotplug would very soon after set the proper MAC?
> > 
> > If so, that is liable to mess up stock ath10k firmware since it will not
> > properly calculate its rx-bssid mask.
> 
> Let's test it then.
> 
> Ben, Felix: I've prepared a big, one in all, test patch for the R7800 -
> that if viable will be split up, upstreamed and merged accordingly.
> 
> This patch contains:
> 
> 0. ath10k and ath10k-ct fixes that implement Felix request to 
>    "call pdev_set_base_macaddr_cmdid before bringing up the first vif".
>    This is in the "976-ath10k-implement-set-base-macaddr" patch.
>    (Note: the ath10k driver had no support code for this function, nor
>    does it mention what the data the pdev_set_base_macaddr_cmdid takes.
>    I assume it's just 6-bytes for the base MAC.) 
> 
>    Ben: Can you please comment if this is all right, or if something
>         needs to be changed? 
> 
> 1. 998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
>    This is an upstream patch
> 
> 2. 950-call-of_get_mac_address-from-device.patch
>    A hack that makes it work. This could be a point of conflict.
> 
> 3. R7800 dts changes
>    I hope they are correct enough. I don't have the hardware to test
>    it.
> 
> 4. (userspace code).
> 
> In the mean time, because this is so much new, experimental stuff. I'll go
> ahead with the ugly firmware patching for now until this is ready for
> prime time.
> 
> Regards,
> Christian
> 

Update: Mathias wrote me yesterday that the ath10k-ct was not working because
the ath10k-ct driver now uses the ath10k-4.19 branch. This (and the missing
"retrieve MAC address from system firmware if provided" for ath10k-ct) patch
has been fixed.


---
From d0b9a5338aca246f77e12cb6858df926252dea90 Mon Sep 17 00:00:00 2001
From: Christian Lamparter <chunkeey@gmail.com>
Date: Sat, 15 Dec 2018 10:56:14 +0100
Subject: [PATCH] ipq806x: R7800: mtd-mac-address test

---
 ...76-ath10k-implement-set-base-macaddr.patch | 172 ++++++++++++++++++
 ...MAC-address-from-system-firmware-if-.patch |  48 +++++
 ...77-ath10k-implement-set-base-macaddr.patch | 172 ++++++++++++++++++
 ...MAC-address-from-system-firmware-if-.patch |  51 ++++++
 ...-call-of_get_mac_address-from-device.patch |  23 +++
 .../etc/hotplug.d/firmware/11-ath10k-caldata  |   3 +-
 .../arch/arm/boot/dts/qcom-ipq8065-r7800.dts  |  34 +++-
 7 files changed, 499 insertions(+), 4 deletions(-)
 create mode 100644 package/kernel/ath10k-ct/patches/976-ath10k-implement-set-base-macaddr.patch
 create mode 100644 package/kernel/ath10k-ct/patches/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
 create mode 100644 package/kernel/mac80211/patches/ath/977-ath10k-implement-set-base-macaddr.patch
 create mode 100644 package/kernel/mac80211/patches/ath/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
 create mode 100644 target/linux/generic/hack-4.14/950-call-of_get_mac_address-from-device.patch

diff --git a/package/kernel/ath10k-ct/patches/976-ath10k-implement-set-base-macaddr.patch b/package/kernel/ath10k-ct/patches/976-ath10k-implement-set-base-macaddr.patch
new file mode 100644
index 0000000000..23495b17cf
--- /dev/null
+++ b/package/kernel/ath10k-ct/patches/976-ath10k-implement-set-base-macaddr.patch
@@ -0,0 +1,172 @@
+--- a/ath10k-4.19/core.c
++++ b/ath10k-4.19/core.c
+@@ -2938,6 +2938,13 @@ int ath10k_core_start(struct ath10k *ar,
+ 		goto err_hif_stop;
+ 	}
+ 
++	status = ath10k_wmi_pdev_set_base_macaddr(ar, ar->mac_addr);
++	if (status) {
++		ath10k_err(ar,
++			   "failed to set base mac address: %d\n", status);
++		goto err_hif_stop;
++	}
++
+ 	/* Some firmware revisions do not properly set up hardware rx filter
+ 	 * registers.
+ 	 *
+--- a/ath10k-4.19/wmi-ops.h
++++ b/ath10k-4.19/wmi-ops.h
+@@ -64,6 +64,8 @@ struct wmi_ops {
+ 
+ 	enum wmi_txbf_conf (*get_txbf_conf_scheme)(struct ath10k *ar);
+ 
++	struct sk_buff *(*gen_pdev_set_base_macaddr)(struct ath10k *ar,
++						     const u8 macaddr[ETH_ALEN]);
+ 	struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
+ 	struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
+ 	struct sk_buff *(*gen_pdev_set_rd)(struct ath10k *ar, u16 rd, u16 rd2g,
+@@ -506,6 +508,22 @@ ath10k_wmi_pdev_set_regdomain(struct ath
+ }
+ 
+ static inline int
++ath10k_wmi_pdev_set_base_macaddr(struct ath10k *ar, const u8 macaddr[ETH_ALEN])
++{
++	struct sk_buff *skb;
++
++	if (!ar->wmi.ops->gen_pdev_set_base_macaddr)
++		return -EOPNOTSUPP;
++
++	skb = ar->wmi.ops->gen_pdev_set_base_macaddr(ar, macaddr);
++	if (IS_ERR(skb))
++		return PTR_ERR(skb);
++
++	return ath10k_wmi_cmd_send(ar, skb,
++				   ar->wmi.cmd->pdev_set_base_macaddr_cmdid);
++}
++
++static inline int
+ ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
+ {
+ 	struct sk_buff *skb;
+--- a/ath10k-4.19/wmi-tlv.c
++++ b/ath10k-4.19/wmi-tlv.c
+@@ -2221,6 +2221,29 @@ ath10k_wmi_tlv_op_gen_peer_create(struct
+ }
+ 
+ static struct sk_buff *
++ath10k_wmi_tlv_op_gen_pdev_set_base_macaddr(struct ath10k *ar,
++					    const u8 addr[ETH_ALEN])
++{
++	struct wmi_pdev_set_base_macaddr_cmd *cmd;
++	struct wmi_tlv *tlv;
++	struct sk_buff *skb;
++
++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
++	if (!skb)
++		return ERR_PTR(-ENOMEM);
++
++	tlv = (void *)skb->data;
++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_BASE_MACADDR_CMD);
++	tlv->len = __cpu_to_le16(sizeof(*cmd));
++	cmd = (void *)tlv->value;
++	ether_addr_copy(cmd->mac_addr.addr, addr);
++
++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set base macaddr\n");
++	return skb;
++}
++
++
++static struct sk_buff *
+ ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
+ 				  const u8 peer_addr[ETH_ALEN])
+ {
+@@ -3921,6 +3944,8 @@ static const struct wmi_ops wmi_tlv_ops
+ 	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr =
++			ath10k_wmi_tlv_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_tlv_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
+--- a/ath10k-4.19/wmi.c
++++ b/ath10k-4.19/wmi.c
+@@ -6545,6 +6545,25 @@ int ath10k_wmi_connect(struct ath10k *ar
+ }
+ 
+ static struct sk_buff *
++ath10k_wmi_op_gen_pdev_set_base_macaddr(struct ath10k *ar,
++					const u8 macaddr[ETH_ALEN])
++{
++	struct wmi_pdev_set_base_macaddr_cmd *cmd;
++	struct sk_buff *skb;
++
++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
++	if (!skb)
++		return ERR_PTR(-ENOMEM);
++
++	cmd = (struct wmi_pdev_set_base_macaddr_cmd *)skb->data;
++	ether_addr_copy(cmd->mac_addr.addr, macaddr);
++
++	ath10k_dbg(ar, ATH10K_DBG_WMI,
++		   "wmi pdev basemac %pM\n", macaddr);
++	return skb;
++}
++
++static struct sk_buff *
+ ath10k_wmi_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
+ 			      u16 ctl2g, u16 ctl5g,
+ 			      enum wmi_dfs_region dfs_reg)
+@@ -9571,6 +9590,7 @@ static const struct wmi_ops wmi_ops = {
+ 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
+@@ -9648,6 +9668,7 @@ static const struct wmi_ops wmi_10_1_ops
+ 	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
+ 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+ 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
+ 	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
+ 	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
+@@ -9704,6 +9725,7 @@ static const struct wmi_ops wmi_10_2_ops
+ 	.pull_fw_stats = ath10k_wmi_10_2_op_pull_fw_stats,
+ 	.gen_init = ath10k_wmi_10_2_op_gen_init,
+ 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	/* .gen_pdev_get_temperature not implemented */
+ 
+ 	/* shared with 10.1 */
+@@ -9775,6 +9797,7 @@ static const struct wmi_ops wmi_10_2_4_o
+ 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
+ 	.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
+ 	.gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 
+ 	/* shared with 10.1 */
+ 	.map_svc = wmi_10x_svc_map,
+@@ -9917,6 +9940,7 @@ static const struct wmi_ops wmi_10_4_ops
+ 	.gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
+ 	.gen_echo = ath10k_wmi_op_gen_echo,
+ 	.gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	.gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
+ 	.gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
+ };
+--- a/ath10k-4.19/wmi.h
++++ b/ath10k-4.19/wmi.h
+@@ -4190,6 +4190,10 @@ struct wmi_pdev_set_param_cmd {
+ 	__le32 param_value;
+ } __packed;
+ 
++struct wmi_pdev_set_base_macaddr_cmd {
++	struct wmi_mac_addr mac_addr;
++} __packed;
++
+ /* valid period is 1 ~ 60000ms, unit in millisecond */
+ #define WMI_PDEV_PARAM_CAL_PERIOD_MAX 60000
+ 
diff --git a/package/kernel/ath10k-ct/patches/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch b/package/kernel/ath10k-ct/patches/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
new file mode 100644
index 0000000000..4da5df1f34
--- /dev/null
+++ b/package/kernel/ath10k-ct/patches/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
@@ -0,0 +1,48 @@
+From 9d5804662ce1f9bdde0a14c3c40940acbbf09538 Mon Sep 17 00:00:00 2001
+From: Brian Norris <briannorris@chromium.org>
+Date: Tue, 28 Aug 2018 19:48:17 +0300
+Subject: [PATCH] ath10k: retrieve MAC address from system firmware if provided
+
+Devices may provide their own MAC address via system firmware (e.g.,
+device tree), especially in the case where the device doesn't have a
+useful EEPROM on which to store its MAC address (e.g., for integrated
+Wifi).
+
+Use the generic device helper to retrieve the MAC address, and (if
+present) honor it above the MAC address advertised by the card.
+
+Signed-off-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/ath10k-4.19/core.c
++++ b/ath10k-4.19/core.c
+@@ -19,6 +19,7 @@
+ #include <linux/module.h>
+ #include <linux/firmware.h>
+ #include <linux/of.h>
++#include <linux/property.h>
+ #include <linux/dmi.h>
+ #include <linux/ctype.h>
+ #include <asm/byteorder.h>
+@@ -3276,6 +3277,8 @@ static int ath10k_core_probe_fw(struct a
+ 		ath10k_debug_print_board_info(ar);
+ 	}
+ 
++	device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr)); pr_info("MAC:ADDR %pM\n", ar->mac_addr);
++
+ 	ret = ath10k_core_init_firmware_features(ar);
+ 	if (ret) {
+ 		ath10k_err(ar, "fatal problem with firmware features: %d\n",
+--- a/ath10k-4.19/wmi.c
++++ b/ath10k-4.19/wmi.c
+@@ -5867,7 +5867,8 @@ int ath10k_wmi_event_ready(struct ath10k
+ 		   arg.mac_addr,
+ 		   __le32_to_cpu(arg.status));
+ 
+-	ether_addr_copy(ar->mac_addr, arg.mac_addr);
++	if (is_zero_ether_addr(ar->mac_addr))
++		ether_addr_copy(ar->mac_addr, arg.mac_addr);
+ 	complete(&ar->wmi.unified_ready);
+ 	return 0;
+ }
diff --git a/package/kernel/mac80211/patches/ath/977-ath10k-implement-set-base-macaddr.patch b/package/kernel/mac80211/patches/ath/977-ath10k-implement-set-base-macaddr.patch
new file mode 100644
index 0000000000..5ec2ff8981
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/977-ath10k-implement-set-base-macaddr.patch
@@ -0,0 +1,172 @@
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -2398,6 +2398,13 @@ int ath10k_core_start(struct ath10k *ar,
+ 		goto err_hif_stop;
+ 	}
+ 
++	status = ath10k_wmi_pdev_set_base_macaddr(ar, ar->mac_addr);
++	if (status) {
++		ath10k_err(ar,
++			   "failed to set base mac address: %d\n", status);
++		goto err_hif_stop;
++	}
++
+ 	/* Some firmware revisions do not properly set up hardware rx filter
+ 	 * registers.
+ 	 *
+--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
+@@ -64,6 +64,8 @@ struct wmi_ops {
+ 
+ 	enum wmi_txbf_conf (*get_txbf_conf_scheme)(struct ath10k *ar);
+ 
++	struct sk_buff *(*gen_pdev_set_base_macaddr)(struct ath10k *ar,
++						     const u8 macaddr[ETH_ALEN]);
+ 	struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
+ 	struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
+ 	struct sk_buff *(*gen_pdev_set_rd)(struct ath10k *ar, u16 rd, u16 rd2g,
+@@ -504,6 +506,22 @@ ath10k_wmi_pdev_set_regdomain(struct ath
+ }
+ 
+ static inline int
++ath10k_wmi_pdev_set_base_macaddr(struct ath10k *ar, const u8 macaddr[ETH_ALEN])
++{
++	struct sk_buff *skb;
++
++	if (!ar->wmi.ops->gen_pdev_set_base_macaddr)
++		return -EOPNOTSUPP;
++
++	skb = ar->wmi.ops->gen_pdev_set_base_macaddr(ar, macaddr);
++	if (IS_ERR(skb))
++		return PTR_ERR(skb);
++
++	return ath10k_wmi_cmd_send(ar, skb,
++				   ar->wmi.cmd->pdev_set_base_macaddr_cmdid);
++}
++
++static inline int
+ ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
+ {
+ 	struct sk_buff *skb;
+--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+@@ -2221,6 +2221,29 @@ ath10k_wmi_tlv_op_gen_peer_create(struct
+ }
+ 
+ static struct sk_buff *
++ath10k_wmi_tlv_op_gen_pdev_set_base_macaddr(struct ath10k *ar,
++					    const u8 addr[ETH_ALEN])
++{
++	struct wmi_pdev_set_base_macaddr_cmd *cmd;
++	struct wmi_tlv *tlv;
++	struct sk_buff *skb;
++
++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
++	if (!skb)
++		return ERR_PTR(-ENOMEM);
++
++	tlv = (void *)skb->data;
++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_BASE_MACADDR_CMD);
++	tlv->len = __cpu_to_le16(sizeof(*cmd));
++	cmd = (void *)tlv->value;
++	ether_addr_copy(cmd->mac_addr.addr, addr);
++
++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set base macaddr\n");
++	return skb;
++}
++
++
++static struct sk_buff *
+ ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
+ 				  const u8 peer_addr[ETH_ALEN])
+ {
+@@ -3921,6 +3944,8 @@ static const struct wmi_ops wmi_tlv_ops
+ 	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr =
++			ath10k_wmi_tlv_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_tlv_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -6127,6 +6127,25 @@ int ath10k_wmi_connect(struct ath10k *ar
+ }
+ 
+ static struct sk_buff *
++ath10k_wmi_op_gen_pdev_set_base_macaddr(struct ath10k *ar,
++					const u8 macaddr[ETH_ALEN])
++{
++	struct wmi_pdev_set_base_macaddr_cmd *cmd;
++	struct sk_buff *skb;
++
++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
++	if (!skb)
++		return ERR_PTR(-ENOMEM);
++
++	cmd = (struct wmi_pdev_set_base_macaddr_cmd *)skb->data;
++	ether_addr_copy(cmd->mac_addr.addr, macaddr);
++
++	ath10k_dbg(ar, ATH10K_DBG_WMI,
++		   "wmi pdev basemac %pM\n", macaddr);
++	return skb;
++}
++
++static struct sk_buff *
+ ath10k_wmi_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
+ 			      u16 ctl2g, u16 ctl5g,
+ 			      enum wmi_dfs_region dfs_reg)
+@@ -8791,6 +8810,7 @@ static const struct wmi_ops wmi_ops = {
+ 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
+@@ -8850,6 +8870,7 @@ static const struct wmi_ops wmi_10_1_ops
+ 	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
+ 	.gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
+ 	.gen_peer_assoc = ath10k_wmi_10_1_op_gen_peer_assoc,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	/* .gen_pdev_get_temperature not implemented */
+ 
+ 	/* shared with main branch */
+@@ -8918,6 +8939,7 @@ static const struct wmi_ops wmi_10_2_ops
+ 	.pull_fw_stats = ath10k_wmi_10_2_op_pull_fw_stats,
+ 	.gen_init = ath10k_wmi_10_2_op_gen_init,
+ 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	/* .gen_pdev_get_temperature not implemented */
+ 
+ 	/* shared with 10.1 */
+@@ -8989,6 +9011,7 @@ static const struct wmi_ops wmi_10_2_4_o
+ 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
+ 	.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
+ 	.gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 
+ 	/* shared with 10.1 */
+ 	.map_svc = wmi_10x_svc_map,
+@@ -9080,6 +9103,7 @@ static const struct wmi_ops wmi_10_4_ops
+ 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+ 	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
+ 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
++	.gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr,
+ 	.gen_init = ath10k_wmi_10_4_op_gen_init,
+ 	.gen_start_scan = ath10k_wmi_op_gen_start_scan,
+ 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
+--- a/drivers/net/wireless/ath/ath10k/wmi.h
++++ b/drivers/net/wireless/ath/ath10k/wmi.h
+@@ -4085,6 +4085,10 @@ struct wmi_pdev_set_param_cmd {
+ 	__le32 param_value;
+ } __packed;
+ 
++struct wmi_pdev_set_base_macaddr_cmd {
++	struct wmi_mac_addr mac_addr;
++} __packed;
++
+ /* valid period is 1 ~ 60000ms, unit in millisecond */
+ #define WMI_PDEV_PARAM_CAL_PERIOD_MAX 60000
+ 
diff --git a/package/kernel/mac80211/patches/ath/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch b/package/kernel/mac80211/patches/ath/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
new file mode 100644
index 0000000000..6795862145
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
@@ -0,0 +1,51 @@
+From 9d5804662ce1f9bdde0a14c3c40940acbbf09538 Mon Sep 17 00:00:00 2001
+From: Brian Norris <briannorris@chromium.org>
+Date: Tue, 28 Aug 2018 19:48:17 +0300
+Subject: [PATCH] ath10k: retrieve MAC address from system firmware if provided
+
+Devices may provide their own MAC address via system firmware (e.g.,
+device tree), especially in the case where the device doesn't have a
+useful EEPROM on which to store its MAC address (e.g., for integrated
+Wifi).
+
+Use the generic device helper to retrieve the MAC address, and (if
+present) honor it above the MAC address advertised by the card.
+
+Signed-off-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/ath/ath10k/core.c | 3 +++
+ drivers/net/wireless/ath/ath10k/wmi.c  | 3 ++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -19,6 +19,7 @@
+ #include <linux/module.h>
+ #include <linux/firmware.h>
+ #include <linux/of.h>
++#include <linux/property.h>
+ #include <linux/dmi.h>
+ #include <linux/ctype.h>
+ #include <asm/byteorder.h>
+@@ -2619,6 +2620,8 @@ static int ath10k_core_probe_fw(struct a
+ 		ath10k_debug_print_board_info(ar);
+ 	}
+ 
++	device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr)); pr_info("MAC:ADDR %pM\n", ar->mac_addr);
++
+ 	ret = ath10k_core_init_firmware_features(ar);
+ 	if (ret) {
+ 		ath10k_err(ar, "fatal problem with firmware features: %d\n",
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -5465,7 +5465,8 @@ int ath10k_wmi_event_ready(struct ath10k
+ 		   arg.mac_addr,
+ 		   __le32_to_cpu(arg.status));
+ 
+-	ether_addr_copy(ar->mac_addr, arg.mac_addr);
++	if (is_zero_ether_addr(ar->mac_addr))
++		ether_addr_copy(ar->mac_addr, arg.mac_addr);
+ 	complete(&ar->wmi.unified_ready);
+ 	return 0;
+ }
diff --git a/target/linux/generic/hack-4.14/950-call-of_get_mac_address-from-device.patch b/target/linux/generic/hack-4.14/950-call-of_get_mac_address-from-device.patch
new file mode 100644
index 0000000000..7e78ceea64
--- /dev/null
+++ b/target/linux/generic/hack-4.14/950-call-of_get_mac_address-from-device.patch
@@ -0,0 +1,23 @@
+--- a/drivers/base/property.c	2018-11-21 09:24:18.000000000 +0100
++++ b/drivers/base/property.c	2018-12-15 13:59:16.894896732 +0100
+@@ -19,6 +19,7 @@
+ #include <linux/property.h>
+ #include <linux/etherdevice.h>
+ #include <linux/phy.h>
++#include <linux/of_net.h>
+ 
+ struct property_set {
+ 	struct device *dev;
+@@ -1186,6 +1187,12 @@ void *device_get_mac_address(struct devi
+ {
+ 	char *res;
+ 
++	res = of_get_mac_address(dev->of_node);
++	if (res && (alen >= ETH_ALEN)) {
++		ether_addr_copy(addr, res);
++		return addr;
++	}
++
+ 	res = device_get_mac_addr(dev, "mac-address", addr, alen);
+ 	if (res)
+ 		return res;
diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
index ba7a8e0b14..915c7df460 100644
--- a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
+++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
@@ -88,8 +88,7 @@ case "$FIRMWARE" in
 		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary PRODUCTDATA 12) +1)
 		;;
 	netgear,d7800 |\
-	netgear,r7500v2 |\
-	netgear,r7800)
+	netgear,r7500v2)
 		ath10kcal_extract "art" 4096 12064
 		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary art 6) +1)
 		;;
diff --git a/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8065-r7800.dts b/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8065-r7800.dts
index c4c9287942..614ab15df6 100644
--- a/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8065-r7800.dts
+++ b/target/linux/ipq806x/files-4.14/arch/arm/boot/dts/qcom-ipq8065-r7800.dts
@@ -255,12 +255,42 @@
 		};
 
 		pcie0: pci@1b500000 {
-			status = "ok";
+			status = "okay";
+
+			bridge@0,0 {
+				reg = <0x00000000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges;
+
+				wifi@1,0 {
+					compatible = "pci168c,0046";
+					reg = <0x00010000 0 0 0 0>;
+
+					mtd-mac-address = <&art 6>;
+					mtd-mac-address-increment = <(1)>;
+				};
+			};
 		};
 
 		pcie1: pci@1b700000 {
-			status = "ok";
+			status = "okay";
 			force_gen1 = <1>;
+
+			bridge@0,0 {
+				reg = <0x00000000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges;
+
+				wifi@1,0 {
+					compatible = "pci168c,0046";
+					reg = <0x00010000 0 0 0 0>;
+
+					mtd-mac-address = <&art 6>;
+					mtd-mac-address-increment = <(2)>;
+				};
+			};
 		};
 
 		nand@1ac00000 {
Mathias Kresin Dec. 17, 2018, 10:20 p.m. UTC | #9
17/12/2018 19:05, Christian Lamparter:
> On Saturday, December 15, 2018 9:10:39 PM CET Christian Lamparter wrote:
>> On Wednesday, November 14, 2018 8:39:22 PM CET Ben Greear wrote:
>>> On 11/01/2018 03:18 AM, Felix Fietkau wrote:
>>>> On 2018-10-28 17:39, Christian Lamparter wrote:
>>>>> Ben Greear reported in his patch:
>>>>> |Subject: netgear r7800: Fix mac address of radios.
>>>>> |
>>>>> |Reloading the driver causes the phyX to change, and that
>>>>> |caused the MAC address to change.
>>>>>
>>>>> This is because all ODM/OEMs except QCA bothered to write
>>>>> the correct MAC address for the ath10k wifi into the
>>>>> calibration data.
>>>> I don't think that's a strong enough reason to further propagate the
>>>> messy calibration data patching.
>>>> How about checking the sysfs device path in the hotplug script instead
>>>> to make sure we're changing the MAC for the right wifi device?
>>>
>>> Would this mean that the NIC is loaded with one (potentially bogus)
>>> MAC, and then hotplug would very soon after set the proper MAC?
>>>
>>> If so, that is liable to mess up stock ath10k firmware since it will not
>>> properly calculate its rx-bssid mask.
>>
>> Let's test it then.
>>
>> Ben, Felix: I've prepared a big, one in all, test patch for the R7800 -
>> that if viable will be split up, upstreamed and merged accordingly.
>>
>> This patch contains:
>>
>> 0. ath10k and ath10k-ct fixes that implement Felix request to
>>     "call pdev_set_base_macaddr_cmdid before bringing up the first vif".
>>     This is in the "976-ath10k-implement-set-base-macaddr" patch.
>>     (Note: the ath10k driver had no support code for this function, nor
>>     does it mention what the data the pdev_set_base_macaddr_cmdid takes.
>>     I assume it's just 6-bytes for the base MAC.)
>>
>>     Ben: Can you please comment if this is all right, or if something
>>          needs to be changed?
>>
>> 1. 998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
>>     This is an upstream patch
>>
>> 2. 950-call-of_get_mac_address-from-device.patch
>>     A hack that makes it work. This could be a point of conflict.
>>
>> 3. R7800 dts changes
>>     I hope they are correct enough. I don't have the hardware to test
>>     it.
>>
>> 4. (userspace code).
>>
>> In the mean time, because this is so much new, experimental stuff. I'll go
>> ahead with the ugly firmware patching for now until this is ready for
>> prime time.
>>
>> Regards,
>> Christian
>>
> 
> Update: Mathias wrote me yesterday that the ath10k-ct was not working because
> the ath10k-ct driver now uses the ath10k-4.19 branch. This (and the missing
> "retrieve MAC address from system firmware if provided" for ath10k-ct) patch
> has been fixed.

The (updated) patches from your staging tree are working fine.

Tested on a Homehub 5a (QCA9880) with ath10k and ath10k-ct using the 
following changes:

diff --git 
a/target/linux/lantiq/base-files/etc/hotplug.d/firmware/11-ath10k-caldata 
b/target/linux/lantiq/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
index 6b4d09dd33..65038180bb 100644
--- 
a/target/linux/lantiq/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
+++ 
b/target/linux/lantiq/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
@@ -40,7 +40,6 @@ case "$FIRMWARE" in
  	case $board in
  		bt,homehub-v5a)
  			ath10k_caldata_extract_ubi "caldata" 20480 2116
-			ath10k_caldata_set_macaddr $(macaddr_add $(mtd_get_mac_binary_ubi 
caldata 4364) +3)
  			;;
  		*)
  			ath10k_caldata_die "board $board is not supported yet"
diff --git 
a/target/linux/lantiq/files-4.14/arch/mips/boot/dts/BTHOMEHUBV5A.dts 
b/target/linux/lantiq/files-4.14/arch/mips/boot/dts/BTHOMEHUBV5A.dts
index c251fc3fc7..3db3a7af19 100644
--- a/target/linux/lantiq/files-4.14/arch/mips/boot/dts/BTHOMEHUBV5A.dts
+++ b/target/linux/lantiq/files-4.14/arch/mips/boot/dts/BTHOMEHUBV5A.dts
@@ -253,7 +253,7 @@
  			#address-cells = <1>;
  			#size-cells = <1>;

-			partition@0 {
+			fake: partition@0 {
  				label = "u-boot";
  				reg = <0x0 0xa0000>;
  				read-only;
@@ -278,6 +278,21 @@
  	};
  };

+&pcie0 {
+	bridge@1,0 {
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0x10000 0 0 0 0>;
+		ranges;
+
+		wifi@2,0 {
+			compatible = "pci168c,003c";
+			reg = <0x20000 0 0 0 0>;
+			mtd-mac-address = <&fake 0>;
+		};
+	};
+};
+
  &pci0 {
  	status = "okay";
  	gpio-reset = <&gpio 21 GPIO_ACTIVE_HIGH>;
Christian Lamparter Dec. 22, 2018, 4:30 p.m. UTC | #10
On Monday, December 17, 2018 11:20:41 PM CET Mathias Kresin wrote:
> 17/12/2018 19:05, Christian Lamparter:
> > On Saturday, December 15, 2018 9:10:39 PM CET Christian Lamparter wrote:
> >> On Wednesday, November 14, 2018 8:39:22 PM CET Ben Greear wrote:
> >>> On 11/01/2018 03:18 AM, Felix Fietkau wrote:
> >>>> On 2018-10-28 17:39, Christian Lamparter wrote:
> >>>>> Ben Greear reported in his patch:
> >>>>> |Subject: netgear r7800: Fix mac address of radios.
> >>>>> |
> >>>>> |Reloading the driver causes the phyX to change, and that
> >>>>> |caused the MAC address to change.
> >>>>>
> >>>>> This is because all ODM/OEMs except QCA bothered to write
> >>>>> the correct MAC address for the ath10k wifi into the
> >>>>> calibration data.
> >>>> I don't think that's a strong enough reason to further propagate the
> >>>> messy calibration data patching.
> >>>> How about checking the sysfs device path in the hotplug script instead
> >>>> to make sure we're changing the MAC for the right wifi device?
> >>>
> >>> Would this mean that the NIC is loaded with one (potentially bogus)
> >>> MAC, and then hotplug would very soon after set the proper MAC?
> >>>
> >>> If so, that is liable to mess up stock ath10k firmware since it will not
> >>> properly calculate its rx-bssid mask.
> >>
> >> Let's test it then.
> >>
> >> Ben, Felix: I've prepared a big, one in all, test patch for the R7800 -
> >> that if viable will be split up, upstreamed and merged accordingly.
> >>
> >> This patch contains:
> >>
> >> 0. ath10k and ath10k-ct fixes that implement Felix request to
> >>     "call pdev_set_base_macaddr_cmdid before bringing up the first vif".
> >>     This is in the "976-ath10k-implement-set-base-macaddr" patch.
> >>     (Note: the ath10k driver had no support code for this function, nor
> >>     does it mention what the data the pdev_set_base_macaddr_cmdid takes.
> >>     I assume it's just 6-bytes for the base MAC.)
> >>
> >>     Ben: Can you please comment if this is all right, or if something
> >>          needs to be changed?
> >>
> >> 1. 998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
> >>     This is an upstream patch
> >>
> >> 2. 950-call-of_get_mac_address-from-device.patch
> >>     A hack that makes it work. This could be a point of conflict.
> >>
> >> 3. R7800 dts changes
> >>     I hope they are correct enough. I don't have the hardware to test
> >>     it.
> >>
> >> 4. (userspace code).
> >>
> >> In the mean time, because this is so much new, experimental stuff. I'll go
> >> ahead with the ugly firmware patching for now until this is ready for
> >> prime time.
> >>
> >> Regards,
> >> Christian
> >>
> > 
> > Update: Mathias wrote me yesterday that the ath10k-ct was not working because
> > the ath10k-ct driver now uses the ath10k-4.19 branch. This (and the missing
> > "retrieve MAC address from system firmware if provided" for ath10k-ct) patch
> > has been fixed.
> 
> The (updated) patches from your staging tree are working fine.
> Tested on a Homehub 5a (QCA9880) with ath10k and ath10k-ct.

Thank you for testing the patches. 

@Ben: Can you please comment if this is all right with regards to vdev/vif
      mask, or if something needs to be changed? Because I can't really move
      forward and look at your "hotplug: Allow renaming wireless phy devices."
      <https://patchwork.ozlabs.org/patch/1014630/> otherwise.

Regards,
Christian
Ben Greear Dec. 26, 2018, 2:30 p.m. UTC | #11
On 12/22/2018 08:30 AM, Christian Lamparter wrote:
> On Monday, December 17, 2018 11:20:41 PM CET Mathias Kresin wrote:
>> 17/12/2018 19:05, Christian Lamparter:
>>> On Saturday, December 15, 2018 9:10:39 PM CET Christian Lamparter wrote:
>>>> On Wednesday, November 14, 2018 8:39:22 PM CET Ben Greear wrote:
>>>>> On 11/01/2018 03:18 AM, Felix Fietkau wrote:
>>>>>> On 2018-10-28 17:39, Christian Lamparter wrote:
>>>>>>> Ben Greear reported in his patch:
>>>>>>> |Subject: netgear r7800: Fix mac address of radios.
>>>>>>> |
>>>>>>> |Reloading the driver causes the phyX to change, and that
>>>>>>> |caused the MAC address to change.
>>>>>>>
>>>>>>> This is because all ODM/OEMs except QCA bothered to write
>>>>>>> the correct MAC address for the ath10k wifi into the
>>>>>>> calibration data.
>>>>>> I don't think that's a strong enough reason to further propagate the
>>>>>> messy calibration data patching.
>>>>>> How about checking the sysfs device path in the hotplug script instead
>>>>>> to make sure we're changing the MAC for the right wifi device?
>>>>>
>>>>> Would this mean that the NIC is loaded with one (potentially bogus)
>>>>> MAC, and then hotplug would very soon after set the proper MAC?
>>>>>
>>>>> If so, that is liable to mess up stock ath10k firmware since it will not
>>>>> properly calculate its rx-bssid mask.
>>>>
>>>> Let's test it then.
>>>>
>>>> Ben, Felix: I've prepared a big, one in all, test patch for the R7800 -
>>>> that if viable will be split up, upstreamed and merged accordingly.
>>>>
>>>> This patch contains:
>>>>
>>>> 0. ath10k and ath10k-ct fixes that implement Felix request to
>>>>     "call pdev_set_base_macaddr_cmdid before bringing up the first vif".
>>>>     This is in the "976-ath10k-implement-set-base-macaddr" patch.
>>>>     (Note: the ath10k driver had no support code for this function, nor
>>>>     does it mention what the data the pdev_set_base_macaddr_cmdid takes.
>>>>     I assume it's just 6-bytes for the base MAC.)
>>>>
>>>>     Ben: Can you please comment if this is all right, or if something
>>>>          needs to be changed?
>>>>
>>>> 1. 998-ath10k-retrieve-MAC-address-from-system-firmware-if-.patch
>>>>     This is an upstream patch
>>>>
>>>> 2. 950-call-of_get_mac_address-from-device.patch
>>>>     A hack that makes it work. This could be a point of conflict.
>>>>
>>>> 3. R7800 dts changes
>>>>     I hope they are correct enough. I don't have the hardware to test
>>>>     it.
>>>>
>>>> 4. (userspace code).
>>>>
>>>> In the mean time, because this is so much new, experimental stuff. I'll go
>>>> ahead with the ugly firmware patching for now until this is ready for
>>>> prime time.
>>>>
>>>> Regards,
>>>> Christian
>>>>
>>>
>>> Update: Mathias wrote me yesterday that the ath10k-ct was not working because
>>> the ath10k-ct driver now uses the ath10k-4.19 branch. This (and the missing
>>> "retrieve MAC address from system firmware if provided" for ath10k-ct) patch
>>> has been fixed.
>>
>> The (updated) patches from your staging tree are working fine.
>> Tested on a Homehub 5a (QCA9880) with ath10k and ath10k-ct.
>
> Thank you for testing the patches.
>
> @Ben: Can you please comment if this is all right with regards to vdev/vif
>       mask, or if something needs to be changed? Because I can't really move
>       forward and look at your "hotplug: Allow renaming wireless phy devices."
>       <https://patchwork.ozlabs.org/patch/1014630/> otherwise.

Hello,

The set-base-macaddr patch appears to match the 10.4 firmware API.

When using CT firmware and driver, you can check the mask by looking at the
fw_regs debugfs file:

[root@lf0313-6477 ~]# cat /debug/ieee80211/wiphy0/ath10k/fw_regs

ath10k Target Register Dump (extras-count: 0)
              =================

            MAC-FILTER-ADDR-L32 0xffffffff
            MAC-FILTER-ADDR-U16 0x0000ffff
....


There is no easy way to get the same data out of stock firmware/driver.

If you have exactly one vdev active, you would expect the mac-filter to be all FFs
as seen above.

Thanks,
Ben
diff mbox series

Patch

diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
index fa49c250f0..1d070603f2 100644
--- a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
+++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
@@ -1,5 +1,21 @@ 
 #!/bin/sh
 
+# xor multiple hex values of the same length
+xor() {
+	local val
+	local ret="0x$1"
+	local retlen=${#1}
+
+	shift
+	while [ -n "$1" ]; do
+		val="0x$1"
+		ret=$((ret ^ val))
+		shift
+	done
+
+	printf "%0${retlen}x" "$ret"
+}
+
 ath10kcal_die() {
 	echo "ath10cal: " "$*"
 	exit 1
@@ -36,6 +52,29 @@  ath10kcal_patch_mac() {
 	macaddr_2bin $mac | dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=6 count=6
 }
 
+ath10kcal_patch_mac_crc() {
+	local mac=$1
+	local mac_offset=6
+	local chksum_offset=2
+	local xor_mac
+	local xor_fw_mac
+	local xor_fw_chksum
+
+	xor_fw_mac=$(hexdump -v -n 6 -s $mac_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE)
+	xor_fw_mac="${xor_fw_mac:0:4} ${xor_fw_mac:4:4} ${xor_fw_mac:8:4}"
+
+	ath10kcal_patch_mac "$mac" && {
+		xor_mac=${mac//:/}
+		xor_mac="${xor_mac:0:4} ${xor_mac:4:4} ${xor_mac:8:4}"
+
+		xor_fw_chksum=$(hexdump -v -n 2 -s $chksum_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE)
+		xor_fw_chksum=$(xor $xor_fw_chksum $xor_fw_mac $xor_mac)
+
+		printf "%b" "\x${xor_fw_chksum:0:2}\x${xor_fw_chksum:2:2}" | \
+			dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=$chksum_offset count=2
+	}
+}
+
 [ -e /lib/firmware/$FIRMWARE ] && exit 0
 
 . /lib/functions.sh
@@ -43,53 +82,64 @@  ath10kcal_patch_mac() {
 
 board=$(board_name)
 
-
 case "$FIRMWARE" in
 "ath10k/pre-cal-pci-0000:01:00.0.bin")
 	case $board in
 	linksys,ea8500)
-		hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr)
 		ath10kcal_extract "art" 4096 12064
+		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +1)
+		;;
+	nec,wg2600hp)
+		ath10kcal_extract "ART" 4096 12064
+		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary PRODUCTDATA 12) +1)
 		;;
 	netgear,d7800 |\
 	netgear,r7500v2 |\
 	netgear,r7800)
 		ath10kcal_extract "art" 4096 12064
+		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary art 6) +1)
 		;;
 	tplink,c2600)
 		ath10kcal_extract "radio" 4096 12064
-# 		ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -1)
+		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary default-mac 8) -1)
 		;;
-	nec,wg2600hp |\
 	tplink,vr2600v)
 		ath10kcal_extract "ART" 4096 12064
+		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary default-mac 0) -1)
 		;;
 	zyxel,nbg6817)
 		ath10kcal_extract "0:ART" 4096 12064
+		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) +1)
 		;;
 	esac
 	;;
 "ath10k/pre-cal-pci-0001:01:00.0.bin")
 	case $board in
 	linksys,ea8500)
-		hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr)
 		ath10kcal_extract "art" 20480 12064
+		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) +2)
+		;;
+	nec,wg2600hp)
+		ath10kcal_extract "ART" 20480 12064
+		ath10kcal_patch_mac_crc $(mtd_get_mac_binary PRODUCTDATA 12)
 		;;
 	netgear,d7800 |\
 	netgear,r7500v2 |\
 	netgear,r7800)
 		ath10kcal_extract "art" 20480 12064
+		ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_binary art 6) +2)
 		;;
 	tplink,c2600)
 		ath10kcal_extract "radio" 20480 12064
-# 		ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -2)
+		ath10kcal_patch_mac_crc $(mtd_get_mac_binary default-mac 8)
 		;;
-	nec,wg2600hp |\
 	tplink,vr2600v)
 		ath10kcal_extract "ART" 20480 12064
+		ath10kcal_patch_mac_crc $(mtd_get_mac_binary default-mac 0)
 		;;
 	zyxel,nbg6817)
 		ath10kcal_extract "0:ART" 20480 12064
+		ath10kcal_patch_mac_crc $(mtd_get_mac_ascii 0:APPSBLENV ethaddr)
 		;;
 	esac
 	;;
diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
deleted file mode 100644
index afa425f075..0000000000
--- a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac
+++ /dev/null
@@ -1,37 +0,0 @@ 
-#!/bin/ash
-
-[ "$ACTION" == "add" ] || exit 0
-
-PHYNBR=${DEVPATH##*/phy}
-
-[ -n $PHYNBR ] || exit 0
-
-. /lib/functions.sh
-. /lib/functions/system.sh
-
-board=$(board_name)
-
-case "$board" in
-	linksys,ea8500)
-		echo $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress
-		;;
-	nec,wg2600hp)
-		echo $(macaddr_add $(mtd_get_mac_binary PRODUCTDATA 12) $((1 - $PHYNBR)) ) > /sys${DEVPATH}/macaddress
-		;;
-	netgear,d7800 |\
-	netgear,r7500v2 |\
-	netgear,r7800)
-		echo $(macaddr_add $(mtd_get_mac_binary art 6)  $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress
-		;;
-	tplink,c2600)
-		echo $(macaddr_add $(mtd_get_mac_binary default-mac 8)  $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress
-		;;
-	tplink,vr2600v)
-		echo $(macaddr_add $(mtd_get_mac_binary default-mac 0)  $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress
-		;;
-	zyxel,nbg6817)
-		echo $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) $((1 - $PHYNBR)) ) > /sys${DEVPATH}/macaddress
-		;;
-	*)
-		;;
-esac