1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-03-09 15:40:20 +00:00

Add latest and patched mac80211 ans hostapd packages

This commit is contained in:
Ycarus 2018-09-07 15:07:38 +02:00
parent e5395f65eb
commit bdff38dfc4
321 changed files with 36273 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,836 @@
#!/bin/sh
. /lib/netifd/netifd-wireless.sh
. /lib/netifd/hostapd.sh
init_wireless_driver "$@"
MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh_max_peer_links
mesh_max_retries mesh_ttl mesh_element_ttl mesh_hwmp_max_preq_retries
mesh_path_refresh_time mesh_min_discovery_timeout mesh_hwmp_active_path_timeout
mesh_hwmp_preq_min_interval mesh_hwmp_net_diameter_traversal_time mesh_hwmp_rootmode
mesh_hwmp_rann_interval mesh_gate_announcements mesh_sync_offset_max_neighor
mesh_rssi_threshold mesh_hwmp_active_path_to_root_timeout mesh_hwmp_root_interval
mesh_hwmp_confirmation_interval mesh_awake_window mesh_plink_timeout"
MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding"
MP_CONFIG_STRING="mesh_power_mode"
drv_mac80211_init_device_config() {
hostapd_common_add_device_config
config_add_string path phy 'macaddr:macaddr'
config_add_string hwmode
config_add_int beacon_int chanbw frag rts
config_add_int rxantenna txantenna antenna_gain txpower distance
config_add_boolean noscan ht_coex
config_add_array ht_capab
config_add_array channels
config_add_boolean \
rxldpc \
short_gi_80 \
short_gi_160 \
tx_stbc_2by1 \
su_beamformer \
su_beamformee \
mu_beamformer \
mu_beamformee \
vht_txop_ps \
htc_vht \
rx_antenna_pattern \
tx_antenna_pattern
config_add_int vht_max_a_mpdu_len_exp vht_max_mpdu vht_link_adapt vht160 rx_stbc tx_stbc
config_add_boolean \
ldpc \
greenfield \
short_gi_20 \
short_gi_40 \
max_amsdu \
dsss_cck_40
}
drv_mac80211_init_iface_config() {
hostapd_common_add_bss_config
config_add_string 'macaddr:macaddr' ifname
config_add_boolean wds powersave
config_add_int maxassoc
config_add_int max_listen_int
config_add_int dtim_period
config_add_int start_disabled
# mesh
config_add_string mesh_id
config_add_int $MP_CONFIG_INT
config_add_boolean $MP_CONFIG_BOOL
config_add_string $MP_CONFIG_STRING
}
mac80211_add_capabilities() {
local __var="$1"; shift
local __mask="$1"; shift
local __out= oifs
oifs="$IFS"
IFS=:
for capab in "$@"; do
set -- $capab
[ "$(($4))" -gt 0 ] || continue
[ "$(($__mask & $2))" -eq "$((${3:-$2}))" ] || continue
__out="$__out[$1]"
done
IFS="$oifs"
export -n -- "$__var=$__out"
}
mac80211_hostapd_setup_base() {
local phy="$1"
json_select config
[ "$auto_channel" -gt 0 ] && channel=acs_survey
[ "$auto_channel" -gt 0 ] && json_get_values channel_list channels
json_get_vars noscan ht_coex
json_get_values ht_capab_list ht_capab
ieee80211n=1
ht_capab=
case "$htmode" in
VHT20|HT20) ;;
HT40*|VHT40|VHT80|VHT160)
case "$hwmode" in
a)
case "$(( ($channel / 4) % 2 ))" in
1) ht_capab="[HT40+]";;
0) ht_capab="[HT40-]";;
esac
;;
*)
case "$htmode" in
HT40+) ht_capab="[HT40+]";;
HT40-) ht_capab="[HT40-]";;
*)
if [ "$channel" -lt 7 ]; then
ht_capab="[HT40+]"
else
ht_capab="[HT40-]"
fi
;;
esac
;;
esac
[ "$auto_channel" -gt 0 ] && ht_capab="[HT40+]"
;;
*) ieee80211n= ;;
esac
[ -n "$ieee80211n" ] && {
append base_cfg "ieee80211n=1" "$N"
set_default ht_coex 0
append base_cfg "ht_coex=$ht_coex" "$N"
json_get_vars \
ldpc:1 \
greenfield:0 \
short_gi_20:1 \
short_gi_40:0 \
tx_stbc:1 \
rx_stbc:3 \
max_amsdu:1 \
dsss_cck_40:1
ht_cap_mask=0
for cap in $(iw phy "$phy" info | grep 'Capabilities:' | cut -d: -f2); do
ht_cap_mask="$(($ht_cap_mask | $cap))"
done
cap_rx_stbc=$((($ht_cap_mask >> 8) & 3))
[ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))"
mac80211_add_capabilities ht_capab_flags $ht_cap_mask \
LDPC:0x1::$ldpc \
GF:0x10::$greenfield \
SHORT-GI-20:0x20::$short_gi_20 \
SHORT-GI-40:0x40::$short_gi_40 \
TX-STBC:0x80::$tx_stbc \
RX-STBC1:0x300:0x100:1 \
RX-STBC12:0x300:0x200:1 \
RX-STBC123:0x300:0x300:1 \
MAX-AMSDU-7935:0x800::$max_amsdu \
DSSS_CCK-40:0x1000::$dsss_cck_40
ht_capab="$ht_capab$ht_capab_flags"
[ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
}
# 802.11ac
enable_ac=0
idx="$channel"
case "$htmode" in
VHT20) enable_ac=1;;
VHT40)
case "$(( ($channel / 4) % 2 ))" in
1) idx=$(($channel + 2));;
0) idx=$(($channel - 2));;
esac
enable_ac=1
append base_cfg "vht_oper_chwidth=0" "$N"
append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
;;
VHT80)
case "$(( ($channel / 4) % 4 ))" in
1) idx=$(($channel + 6));;
2) idx=$(($channel + 2));;
3) idx=$(($channel - 2));;
0) idx=$(($channel - 6));;
esac
enable_ac=1
append base_cfg "vht_oper_chwidth=1" "$N"
append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
;;
VHT160)
case "$channel" in
36|40|44|48|52|56|60|64) idx=50;;
100|104|108|112|116|120|124|128) idx=114;;
esac
enable_ac=1
append base_cfg "vht_oper_chwidth=2" "$N"
append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
;;
esac
if [ "$enable_ac" != "0" ]; then
json_get_vars \
rxldpc:1 \
short_gi_80:1 \
short_gi_160:1 \
tx_stbc_2by1:1 \
su_beamformer:1 \
su_beamformee:1 \
mu_beamformer:1 \
mu_beamformee:1 \
vht_txop_ps:1 \
htc_vht:1 \
rx_antenna_pattern:1 \
tx_antenna_pattern:1 \
vht_max_a_mpdu_len_exp:7 \
vht_max_mpdu:11454 \
rx_stbc:4 \
vht_link_adapt:3 \
vht160:2
append base_cfg "ieee80211ac=1" "$N"
vht_cap=0
for cap in $(iw phy "$phy" info | awk -F "[()]" '/VHT Capabilities/ { print $2 }'); do
vht_cap="$(($vht_cap | $cap))"
done
cap_rx_stbc=$((($vht_cap >> 8) & 7))
[ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))"
mac80211_add_capabilities vht_capab $vht_cap \
RXLDPC:0x10::$rxldpc \
SHORT-GI-80:0x20::$short_gi_80 \
SHORT-GI-160:0x40::$short_gi_160 \
TX-STBC-2BY1:0x80::$tx_stbc_2by1 \
SU-BEAMFORMER:0x800::$su_beamformer \
SU-BEAMFORMEE:0x1000::$su_beamformee \
MU-BEAMFORMER:0x80000::$mu_beamformer \
MU-BEAMFORMEE:0x100000::$mu_beamformee \
VHT-TXOP-PS:0x200000::$vht_txop_ps \
HTC-VHT:0x400000::$htc_vht \
RX-ANTENNA-PATTERN:0x10000000::$rx_antenna_pattern \
TX-ANTENNA-PATTERN:0x20000000::$tx_antenna_pattern \
RX-STBC-1:0x700:0x100:1 \
RX-STBC-12:0x700:0x200:1 \
RX-STBC-123:0x700:0x300:1 \
RX-STBC-1234:0x700:0x400:1 \
# supported Channel widths
vht160_hw=0
[ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \
vht160_hw=1
[ "$(($vht_cap & 12))" -eq 8 -a 2 -le "$vht160" ] && \
vht160_hw=2
[ "$vht160_hw" = 1 ] && vht_capab="$vht_capab[VHT160]"
[ "$vht160_hw" = 2 ] && vht_capab="$vht_capab[VHT160-80PLUS80]"
# maximum MPDU length
vht_max_mpdu_hw=3895
[ "$(($vht_cap & 3))" -ge 1 -a 7991 -le "$vht_max_mpdu" ] && \
vht_max_mpdu_hw=7991
[ "$(($vht_cap & 3))" -ge 2 -a 11454 -le "$vht_max_mpdu" ] && \
vht_max_mpdu_hw=11454
[ "$vht_max_mpdu_hw" != 3895 ] && \
vht_capab="$vht_capab[MAX-MPDU-$vht_max_mpdu_hw]"
# maximum A-MPDU length exponent
vht_max_a_mpdu_len_exp_hw=0
[ "$(($vht_cap & 58720256))" -ge 8388608 -a 1 -le "$vht_max_a_mpdu_len_exp" ] && \
vht_max_a_mpdu_len_exp_hw=1
[ "$(($vht_cap & 58720256))" -ge 16777216 -a 2 -le "$vht_max_a_mpdu_len_exp" ] && \
vht_max_a_mpdu_len_exp_hw=2
[ "$(($vht_cap & 58720256))" -ge 25165824 -a 3 -le "$vht_max_a_mpdu_len_exp" ] && \
vht_max_a_mpdu_len_exp_hw=3
[ "$(($vht_cap & 58720256))" -ge 33554432 -a 4 -le "$vht_max_a_mpdu_len_exp" ] && \
vht_max_a_mpdu_len_exp_hw=4
[ "$(($vht_cap & 58720256))" -ge 41943040 -a 5 -le "$vht_max_a_mpdu_len_exp" ] && \
vht_max_a_mpdu_len_exp_hw=5
[ "$(($vht_cap & 58720256))" -ge 50331648 -a 6 -le "$vht_max_a_mpdu_len_exp" ] && \
vht_max_a_mpdu_len_exp_hw=6
[ "$(($vht_cap & 58720256))" -ge 58720256 -a 7 -le "$vht_max_a_mpdu_len_exp" ] && \
vht_max_a_mpdu_len_exp_hw=7
vht_capab="$vht_capab[MAX-A-MPDU-LEN-EXP$vht_max_a_mpdu_len_exp_hw]"
# whether or not the STA supports link adaptation using VHT variant
vht_link_adapt_hw=0
[ "$(($vht_cap & 201326592))" -ge 134217728 -a 2 -le "$vht_link_adapt" ] && \
vht_link_adapt_hw=2
[ "$(($vht_cap & 201326592))" -ge 201326592 -a 3 -le "$vht_link_adapt" ] && \
vht_link_adapt_hw=3
[ "$vht_link_adapt_hw" != 0 ] && \
vht_capab="$vht_capab[VHT-LINK-ADAPT-$vht_link_adapt_hw]"
[ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N"
fi
hostapd_prepare_device_config "$hostapd_conf_file" nl80211
cat >> "$hostapd_conf_file" <<EOF
${channel:+channel=$channel}
${channel_list:+chanlist=$channel_list}
${noscan:+noscan=$noscan}
$base_cfg
EOF
json_select ..
}
mac80211_hostapd_setup_bss() {
local phy="$1"
local ifname="$2"
local macaddr="$3"
local type="$4"
hostapd_cfg=
append hostapd_cfg "$type=$ifname" "$N"
hostapd_set_bss_options hostapd_cfg "$vif" || return 1
json_get_vars wds dtim_period max_listen_int start_disabled
set_default wds 0
set_default start_disabled 0
[ "$wds" -gt 0 ] && append hostapd_cfg "wds_sta=1" "$N"
[ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N"
cat >> /var/run/hostapd-$phy.conf <<EOF
$hostapd_cfg
bssid=$macaddr
${dtim_period:+dtim_period=$dtim_period}
${max_listen_int:+max_listen_interval=$max_listen_int}
EOF
}
mac80211_get_addr() {
local phy="$1"
local idx="$(($2 + 1))"
head -n $(($macidx + 1)) /sys/class/ieee80211/${phy}/addresses | tail -n1
}
mac80211_generate_mac() {
local phy="$1"
local id="${macidx:-0}"
local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)"
local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)"
[ "$mask" = "00:00:00:00:00:00" ] && {
mask="ff:ff:ff:ff:ff:ff";
[ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt 1 ] && {
addr="$(mac80211_get_addr "$phy" "$id")"
[ -n "$addr" ] && {
echo "$addr"
return
}
}
}
local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS"
local mask1=$1
local mask6=$6
local oIFS="$IFS"; IFS=":"; set -- $ref; IFS="$oIFS"
macidx=$(($id + 1))
[ "$((0x$mask1))" -gt 0 ] && {
b1="0x$1"
[ "$id" -gt 0 ] && \
b1=$(($b1 ^ ((($id - 1) << 2) | 0x2)))
printf "%02x:%s:%s:%s:%s:%s" $b1 $2 $3 $4 $5 $6
return
}
[ "$((0x$mask6))" -lt 255 ] && {
printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $(( 0x$6 ^ $id ))
return
}
off2=$(( (0x$6 + $id) / 0x100 ))
printf "%s:%s:%s:%s:%02x:%02x" \
$1 $2 $3 $4 \
$(( (0x$5 + $off2) % 0x100 )) \
$(( (0x$6 + $id) % 0x100 ))
}
find_phy() {
[ -n "$phy" -a -d /sys/class/ieee80211/$phy ] && return 0
[ -n "$path" ] && {
for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
case "$(readlink -f /sys/class/ieee80211/$phy/device)" in
*$path) return 0;;
esac
done
}
[ -n "$macaddr" ] && {
for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && return 0
done
}
return 1
}
mac80211_check_ap() {
has_ap=1
}
mac80211_iw_interface_add() {
local phy="$1"
local ifname="$2"
local type="$3"
local wdsflag="$4"
local rc
iw phy "$phy" interface add "$ifname" type "$type" $wdsflag
rc="$?"
[ "$rc" = 233 ] && {
# Device might have just been deleted, give the kernel some time to finish cleaning it up
sleep 1
iw phy "$phy" interface add "$ifname" type "$type" $wdsflag
rc="$?"
}
[ "$rc" = 233 -o "$rc" = 161 ] && {
# Device might not support virtual interfaces, so the interface never got deleted in the first place.
# Check if the interface already exists, and avoid failing in this case.
ip link show dev "$ifname" >/dev/null 2>/dev/null && rc=0
}
[ "$rc" != 0 ] && wireless_setup_failed INTERFACE_CREATION_FAILED
return $rc
}
mac80211_prepare_vif() {
json_select config
json_get_vars ifname mode ssid wds powersave macaddr
[ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}"
if_idx=$((${if_idx:-0} + 1))
set_default wds 0
set_default powersave 0
json_select ..
[ -n "$macaddr" ] || {
macaddr="$(mac80211_generate_mac $phy)"
macidx="$(($macidx + 1))"
}
json_add_object data
json_add_string ifname "$ifname"
json_close_object
json_select config
# It is far easier to delete and create the desired interface
case "$mode" in
adhoc)
mac80211_iw_interface_add "$phy" "$ifname" adhoc || return
;;
ap)
# Hostapd will handle recreating the interface and
# subsequent virtual APs belonging to the same PHY
if [ -n "$hostapd_ctrl" ]; then
type=bss
else
type=interface
fi
mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
[ -n "$hostapd_ctrl" ] || {
mac80211_iw_interface_add "$phy" "$ifname" __ap || return
hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
}
;;
mesh)
mac80211_iw_interface_add "$phy" "$ifname" mp || return
;;
monitor)
mac80211_iw_interface_add "$phy" "$ifname" monitor || return
;;
sta)
local wdsflag=
staidx="$(($staidx + 1))"
[ "$wds" -gt 0 ] && wdsflag="4addr on"
mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return
[ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
iw "$ifname" set power_save "$powersave"
;;
esac
case "$mode" in
monitor|mesh)
[ "$auto_channel" -gt 0 ] || iw dev "$ifname" set channel "$channel" $htmode
;;
esac
if [ "$mode" != "ap" ]; then
# ALL ap functionality will be passed to hostapd
# All interfaces must have unique mac addresses
# which can either be explicitly set in the device
# section, or automatically generated
ip link set dev "$ifname" address "$macaddr"
fi
json_select ..
}
mac80211_setup_supplicant() {
wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
if [ "$mode" = "sta" ]; then
wpa_supplicant_add_network "$ifname"
else
wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
fi
wpa_supplicant_run "$ifname" ${hostapd_ctrl:+-H $hostapd_ctrl}
}
mac80211_setup_supplicant_noctl() {
wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
wpa_supplicant_run "$ifname"
}
mac80211_setup_adhoc_htmode() {
case "$htmode" in
VHT20|HT20) ibss_htmode=HT20;;
HT40*|VHT40|VHT160)
case "$hwmode" in
a)
case "$(( ($channel / 4) % 2 ))" in
1) ibss_htmode="HT40+" ;;
0) ibss_htmode="HT40-";;
esac
;;
*)
case "$htmode" in
HT40+) ibss_htmode="HT40+";;
HT40-) ibss_htmode="HT40-";;
*)
if [ "$channel" -lt 7 ]; then
ibss_htmode="HT40+"
else
ibss_htmode="HT40-"
fi
;;
esac
;;
esac
[ "$auto_channel" -gt 0 ] && ibss_htmode="HT40+"
;;
VHT80)
ibss_htmode="80MHZ"
;;
NONE|NOHT)
ibss_htmode="NOHT"
;;
*) ibss_htmode="" ;;
esac
}
mac80211_setup_adhoc() {
json_get_vars bssid ssid key mcast_rate
keyspec=
[ "$auth_type" = "wep" ] && {
set_default key 1
case "$key" in
[1234])
local idx
for idx in 1 2 3 4; do
json_get_var ikey "key$idx"
[ -n "$ikey" ] && {
ikey="$(($idx - 1)):$(prepare_key_wep "$ikey")"
[ $idx -eq $key ] && ikey="d:$ikey"
append keyspec "$ikey"
}
done
;;
*)
append keyspec "d:0:$(prepare_key_wep "$key")"
;;
esac
}
brstr=
for br in $basic_rate_list; do
wpa_supplicant_add_rate brstr "$br"
done
mcval=
[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
iw dev "$ifname" ibss join "$ssid" $freq $ibss_htmode fixed-freq $bssid \
beacon-interval $beacon_int \
${brstr:+basic-rates $brstr} \
${mcval:+mcast-rate $mcval} \
${keyspec:+keys $keyspec}
}
mac80211_setup_mesh() {
json_get_vars ssid mesh_id mcast_rate
mcval=
[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
[ -n "$mesh_id" ] && ssid="$mesh_id"
case "$htmode" in
VHT20|HT20) mesh_htmode=HT20;;
HT40*|VHT40)
case "$hwmode" in
a)
case "$(( ($channel / 4) % 2 ))" in
1) mesh_htmode="HT40+" ;;
0) mesh_htmode="HT40-";;
esac
;;
*)
case "$htmode" in
HT40+) mesh_htmode="HT40+";;
HT40-) mesh_htmode="HT40-";;
*)
if [ "$channel" -lt 7 ]; then
mesh_htmode="HT40+"
else
mesh_htmode="HT40-"
fi
;;
esac
;;
esac
;;
VHT80)
mesh_htmode="80Mhz"
;;
VHT160)
mesh_htmode="160Mhz"
;;
*) mesh_htmode="NOHT" ;;
esac
iw dev "$ifname" mesh join "$ssid" freq $freq $mesh_htmode \
${mcval:+mcast-rate $mcval} \
beacon-interval $beacon_int
}
mac80211_setup_vif() {
local name="$1"
local failed
json_select data
json_get_vars ifname
json_select ..
json_select config
json_get_vars mode
json_get_var vif_txpower txpower
ip link set dev "$ifname" up || {
wireless_setup_vif_failed IFUP_ERROR
json_select ..
return
}
set_default vif_txpower "$txpower"
[ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
case "$mode" in
mesh)
wireless_vif_parse_encryption
freq="$(get_freq "$phy" "$channel")"
if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ] || chan_is_dfs "$phy" "$channel"; then
mac80211_setup_supplicant || failed=1
else
mac80211_setup_mesh
fi
for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do
json_get_var mp_val "$var"
[ -n "$mp_val" ] && iw dev "$ifname" set mesh_param "$var" "$mp_val"
done
;;
adhoc)
wireless_vif_parse_encryption
mac80211_setup_adhoc_htmode
if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
freq="$(get_freq "$phy" "$channel")"
mac80211_setup_supplicant_noctl || failed=1
else
mac80211_setup_adhoc
fi
;;
sta)
mac80211_setup_supplicant || failed=1
;;
esac
json_select ..
[ -n "$failed" ] || wireless_add_vif "$name" "$ifname"
}
get_freq() {
local phy="$1"
local chan="$2"
iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep MHz | awk '{print $2}'
}
chan_is_dfs() {
local phy="$1"
local chan="$2"
iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep -q "MHz.*radar detection"
return $!
}
mac80211_interface_cleanup() {
local phy="$1"
for wdev in $(list_phy_interfaces "$phy"); do
ip link set dev "$wdev" down 2>/dev/null
iw dev "$wdev" del
done
}
drv_mac80211_cleanup() {
hostapd_common_cleanup
}
drv_mac80211_setup() {
json_select config
json_get_vars \
phy macaddr path \
country chanbw distance \
txpower antenna_gain \
rxantenna txantenna \
frag rts beacon_int:100 htmode
json_get_values basic_rate_list basic_rate
json_select ..
find_phy || {
echo "Could not find PHY for device '$1'"
wireless_set_retry 0
return 1
}
wireless_set_data phy="$phy"
mac80211_interface_cleanup "$phy"
# convert channel to frequency
[ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel")"
[ -n "$country" ] && {
iw reg get | grep -q "^country $country:" || {
iw reg set "$country"
sleep 1
}
}
hostapd_conf_file="/var/run/hostapd-$phy.conf"
no_ap=1
macidx=0
staidx=0
[ -n "$chanbw" ] && {
for file in /sys/kernel/debug/ieee80211/$phy/ath9k/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do
[ -f "$file" ] && echo "$chanbw" > "$file"
done
}
set_default rxantenna all
set_default txantenna all
set_default distance 0
set_default antenna_gain 0
iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
iw phy "$phy" set antenna_gain $antenna_gain
iw phy "$phy" set distance "$distance"
[ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}"
[ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}"
has_ap=
hostapd_ctrl=
for_each_interface "ap" mac80211_check_ap
rm -f "$hostapd_conf_file"
[ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy"
for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif
for_each_interface "ap" mac80211_prepare_vif
[ -n "$hostapd_ctrl" ] && {
/usr/sbin/hostapd -s -P /var/run/wifi-$phy.pid -B "$hostapd_conf_file"
ret="$?"
wireless_add_process "$(cat /var/run/wifi-$phy.pid)" "/usr/sbin/hostapd" 1
[ "$ret" != 0 ] && {
wireless_setup_failed HOSTAPD_START_FAILED
return
}
}
for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
wireless_set_up
}
list_phy_interfaces() {
local phy="$1"
if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then
ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null;
else
ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g'
fi
}
drv_mac80211_teardown() {
wireless_process_kill_all
json_select data
json_get_vars phy
json_select ..
mac80211_interface_cleanup "$phy"
}
add_driver mac80211

View file

@ -0,0 +1,132 @@
#!/bin/sh
append DRIVERS "mac80211"
lookup_phy() {
[ -n "$phy" ] && {
[ -d /sys/class/ieee80211/$phy ] && return
}
local devpath
config_get devpath "$device" path
[ -n "$devpath" ] && {
for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
case "$(readlink -f /sys/class/ieee80211/$phy/device)" in
*$devpath) return;;
esac
done
}
local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
[ -n "$macaddr" ] && {
for _phy in /sys/class/ieee80211/*; do
[ -e "$_phy" ] || continue
[ "$macaddr" = "$(cat ${_phy}/macaddress)" ] || continue
phy="${_phy##*/}"
return
done
}
phy=
return
}
find_mac80211_phy() {
local device="$1"
config_get phy "$device" phy
lookup_phy
[ -n "$phy" -a -d "/sys/class/ieee80211/$phy" ] || {
echo "PHY for wifi device $1 not found"
return 1
}
config_set "$device" phy "$phy"
config_get macaddr "$device" macaddr
[ -z "$macaddr" ] && {
config_set "$device" macaddr "$(cat /sys/class/ieee80211/${phy}/macaddress)"
}
return 0
}
check_mac80211_device() {
config_get phy "$1" phy
[ -z "$phy" ] && {
find_mac80211_phy "$1" >/dev/null || return 0
config_get phy "$1" phy
}
[ "$phy" = "$dev" ] && found=1
}
detect_mac80211() {
devidx=0
config_load wireless
while :; do
config_get type "radio$devidx" type
[ -n "$type" ] || break
devidx=$(($devidx + 1))
done
for _dev in /sys/class/ieee80211/*; do
[ -e "$_dev" ] || continue
dev="${_dev##*/}"
found=0
config_foreach check_mac80211_device wifi-device
[ "$found" -gt 0 ] && continue
mode_band="g"
channel="11"
htmode=""
ht_capab=""
iw phy "$dev" info | grep -q 'Capabilities:' && htmode=HT20
iw phy "$dev" info | grep -q '5180 MHz' && {
mode_band="a"
channel="36"
iw phy "$dev" info | grep -q 'VHT Capabilities' && htmode="VHT80"
}
[ -n "$htmode" ] && ht_capab="set wireless.radio${devidx}.htmode=$htmode"
if [ -x /usr/bin/readlink -a -h /sys/class/ieee80211/${dev} ]; then
path="$(readlink -f /sys/class/ieee80211/${dev}/device)"
else
path=""
fi
macaddr="$(cat /sys/class/ieee80211/${dev}/macaddress)"
if [ -n "$path" ]; then
path="${path##/sys/devices/}"
case "$path" in
platform*/pci*) path="${path##platform/}";;
esac
dev_id="set wireless.radio${devidx}.path='$path'"
elif [ "$macaddr" != "00:00:00:00:00:00" ]; then
dev_id="set wireless.radio${devidx}.macaddr=$macaddr"
else
dev_id="set wireless.radio${devidx}.phy=$dev"
fi
uci -q batch <<-EOF
set wireless.radio${devidx}=wifi-device
set wireless.radio${devidx}.type=mac80211
set wireless.radio${devidx}.channel=${channel}
set wireless.radio${devidx}.hwmode=11${mode_band}
${dev_id}
${ht_capab}
set wireless.radio${devidx}.disabled=1
set wireless.default_radio${devidx}=wifi-iface
set wireless.default_radio${devidx}.device=radio${devidx}
set wireless.default_radio${devidx}.network=lan
set wireless.default_radio${devidx}.mode=ap
set wireless.default_radio${devidx}.ssid=OpenWrt
set wireless.default_radio${devidx}.encryption=none
EOF
uci -q commit wireless
devidx=$(($devidx + 1))
done
}

View file

@ -0,0 +1,5 @@
#!/bin/sh
[ "${ACTION}" = "add" ] && {
/sbin/wifi config
}

View file

@ -0,0 +1,14 @@
--- a/kconf/Makefile
+++ b/kconf/Makefile
@@ -1,9 +1,9 @@
-CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
+CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS
LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o
conf: conf.o zconf.tab.o
-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE
+mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags)
mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
mconf: CFLAGS += $(mconf_CFLAGS)

View file

@ -0,0 +1,167 @@
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
ifeq ($(KERNELRELEASE),)
MAKEFLAGS += --no-print-directory
-SHELL := /bin/bash
+SHELL := /usr/bin/env bash
BACKPORT_DIR := $(shell pwd)
KMODDIR ?= updates
@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/
KERNEL_CONFIG := $(KLIB_BUILD)/.config
KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile
CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//')
+STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5)
export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG
@@ -36,7 +37,8 @@ mrproper:
@rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel
@rm -f backport-include/backport/autoconf.h
-.DEFAULT:
+.SILENT: $(STAMP_KERNEL_CONFIG)
+$(STAMP_KERNEL_CONFIG):
@set -e ; test -f local-symbols || ( \
echo "/--------------" ;\
echo "| You shouldn't run make in the backports tree, but only in" ;\
@@ -60,57 +62,61 @@ mrproper:
echo "| (that isn't currently running.)" ;\
echo "\\--" ;\
false)
- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\
- then \
- echo -n "Generating local configuration database from kernel ..." ;\
- grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
- while read l ; do \
- if [ "$${l:0:7}" != "CONFIG_" ] ; then \
- continue ;\
- fi ;\
- l=$${l:7} ;\
- n=$${l%%=*} ;\
- v=$${l#*=} ;\
- if [ "$$v" = "m" ] ; then \
- echo config $$n ;\
- echo ' tristate' ;\
- elif [ "$$v" = "y" ] ; then \
- echo config $$n ;\
- echo ' bool' ;\
- else \
- continue ;\
- fi ;\
- echo " default $$v" ;\
- echo "" ;\
- done \
- ) > Kconfig.kernel ;\
- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
- sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\
- test "$$kver" != "" || echo "Kernel version parse failed!" ;\
- test "$$kver" != "" ;\
- kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
- kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
- kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
- print=0 ;\
- for v in $$kvers ; do \
- if [ "$$print" = "1" ] ; then \
- echo config KERNEL_$$(echo $$v | tr . _) ;\
- echo " def_bool y" ;\
- fi ;\
- if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
- done > Kconfig.versions ;\
- # RHEL as well, sadly we need to grep for it ;\
- RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
- for v in $$(seq 0 $$RHEL_MINOR) ; do \
- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
- echo " def_bool y" ;\
- done >> Kconfig.versions ;\
- echo " done." ;\
- fi ;\
- echo "$(CONFIG_MD5)" > .kernel_config_md5
+ @rm -f .kernel_config_md5_*
+ @touch $@
+
+Kconfig.kernel: $(STAMP_KERNEL_CONFIG) local-symbols
+ @printf "Generating local configuration database from kernel ..."
+ @grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
+ while read l ; do \
+ if [ "$${l:0:7}" != "CONFIG_" ] ; then \
+ continue ;\
+ fi ;\
+ l=$${l:7} ;\
+ n=$${l%%=*} ;\
+ v=$${l#*=} ;\
+ if [ "$$v" = "m" ] ; then \
+ echo config $$n ;\
+ echo ' tristate' ;\
+ elif [ "$$v" = "y" ] ; then \
+ echo config $$n ;\
+ echo ' bool' ;\
+ else \
+ continue ;\
+ fi ;\
+ echo " default $$v" ;\
+ echo "" ;\
+ done \
+ ) > $@
+ @echo " done."
+
+Kconfig.versions: Kconfig.kernel
+ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
+ sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\
+ test "$$kver" != "" || echo "Kernel version parse failed!" ;\
+ test "$$kver" != "" ;\
+ kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
+ kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
+ kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
+ print=0 ;\
+ for v in $$kvers ; do \
+ if [ "$$print" = "1" ] ; then \
+ echo config KERNEL_$$(echo $$v | tr . _) ;\
+ echo " def_bool y" ;\
+ fi ;\
+ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
+ done > $@
+ @RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
+ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
+ RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
+ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
+ for v in $$(seq 0 $$RHEL_MINOR) ; do \
+ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
+ echo " def_bool y" ;\
+ done >> $@
+
+.DEFAULT:
+ @$(MAKE) Kconfig.versions
@$(MAKE) -f Makefile.real "$@"
.PHONY: defconfig-help
--- a/Makefile.real
+++ b/Makefile.real
@@ -59,7 +59,7 @@ defconfig-%::
backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
@$(MAKE) oldconfig
- @echo -n "Building backport-include/backport/autoconf.h ..."
+ @printf "Building backport-include/backport/autoconf.h ..."
@grep -f local-symbols .config | ( \
echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\
echo "#define COMPAT_AUTOCONF_INCLUDED" ;\
@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c
esac ;\
done ;\
echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\
- ) > backport-include/backport/autoconf.h
+ ) > $@.new
+ @if cmp -s $@ $@.new; then \
+ rm -f $@.new; \
+ else \
+ mv $@.new $@; \
+ fi
@echo " done."
.PHONY: modules

View file

@ -0,0 +1,64 @@
--- a/kconf/conf.c
+++ b/kconf/conf.c
@@ -594,40 +594,12 @@ int main(int ac, char **av)
case oldconfig:
case listnewconfig:
case olddefconfig:
- conf_read(NULL);
- break;
case allnoconfig:
case allyesconfig:
case allmodconfig:
case alldefconfig:
case randconfig:
- name = getenv("KCONFIG_ALLCONFIG");
- if (!name)
- break;
- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
- if (conf_read_simple(name, S_DEF_USER)) {
- fprintf(stderr,
- _("*** Can't read seed configuration \"%s\"!\n"),
- name);
- exit(1);
- }
- break;
- }
- switch (input_mode) {
- case allnoconfig: name = "allno.config"; break;
- case allyesconfig: name = "allyes.config"; break;
- case allmodconfig: name = "allmod.config"; break;
- case alldefconfig: name = "alldef.config"; break;
- case randconfig: name = "allrandom.config"; break;
- default: break;
- }
- if (conf_read_simple(name, S_DEF_USER) &&
- conf_read_simple("all.config", S_DEF_USER)) {
- fprintf(stderr,
- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
- name);
- exit(1);
- }
+ conf_read(NULL);
break;
default:
break;
--- a/kconf/confdata.c
+++ b/kconf/confdata.c
@@ -1170,6 +1170,8 @@ bool conf_set_all_new_symbols(enum conf_
}
bool has_changed = false;
+ sym_clear_all_valid();
+
for_all_symbols(i, sym) {
if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
continue;
@@ -1213,8 +1215,6 @@ bool conf_set_all_new_symbols(enum conf_
}
- sym_clear_all_valid();
-
/*
* We have different type of choice blocks.
* If curr.tri equals to mod then we can select several

View file

@ -0,0 +1,34 @@
--- a/compat/main.c
+++ b/compat/main.c
@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL");
#error "You need a CPTCFG_VERSION"
#endif
-static char *backported_kernel_name = CPTCFG_KERNEL_NAME;
-
-module_param(backported_kernel_name, charp, 0400);
-MODULE_PARM_DESC(backported_kernel_name,
- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")");
-
-#ifdef BACKPORTS_GIT_TRACKED
-static char *backports_tracker_id = BACKPORTS_GIT_TRACKED;
-module_param(backports_tracker_id, charp, 0400);
-MODULE_PARM_DESC(backports_tracker_id,
- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")");
-#else
-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION;
-static char *backports_version = CPTCFG_VERSION;
-
-module_param(backported_kernel_version, charp, 0400);
-MODULE_PARM_DESC(backported_kernel_version,
- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")");
-
-module_param(backports_version, charp, 0400);
-MODULE_PARM_DESC(backports_version,
- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")");
-
-#endif
-
void backport_dependency_symbol(void)
{
}

View file

@ -0,0 +1,28 @@
--- a/backport-include/linux/kconfig.h
+++ b/backport-include/linux/kconfig.h
@@ -5,6 +5,8 @@
#include_next <linux/kconfig.h>
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
+
#ifndef __ARG_PLACEHOLDER_1
#define __ARG_PLACEHOLDER_1 0,
#define config_enabled(cfg) _config_enabled(cfg)
@@ -16,6 +18,7 @@
* 3.1 - 3.3 had a broken version of this, so undef
* (they didn't have __ARG_PLACEHOLDER_1)
*/
+
#undef IS_ENABLED
#define IS_ENABLED(option) \
(config_enabled(option) || config_enabled(option##_MODULE))
@@ -31,6 +34,8 @@
#undef IS_BUILTIN
#define IS_BUILTIN(option) config_enabled(option)
+#endif
+
#ifndef IS_REACHABLE
/*
* IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled

View file

@ -0,0 +1,11 @@
--- a/compat/Makefile
+++ b/compat/Makefile
@@ -70,8 +70,6 @@ quiet_cmd_build_OID_registry = GEN $
cmd_build_OID_registry = perl $(src)/build_OID_registry $< $@
compat-$(CPTCFG_BPAUTO_ASN1_DECODER) += lib-asn1_decoder.o
compat-$(CPTCFG_BPAUTO_BUILD_SYSTEM_DATA_VERIFICATION) += lib-oid_registry.o
-skcipher-objs += crypto-skcipher.o
-obj-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += skcipher.o
compat-$(CPTCFG_BPAUTO_RHASHTABLE) += lib-rhashtable.o
cordic-objs += lib-cordic.o
obj-$(CPTCFG_BPAUTO_BUILD_CORDIC) += cordic.o

View file

@ -0,0 +1,10 @@
--- a/compat/backport-4.12.c
+++ b/compat/backport-4.12.c
@@ -225,6 +225,7 @@ int bp_extack_genl_register_family(struc
/* copy this since the family might access it directly */
family->attrbuf = copy->family.attrbuf;
+ family->mcgrp_offset = copy->family.mcgrp_offset;
mutex_lock(&copies_mutex);
list_add_tail(&copy->list, &copies_list);

View file

@ -0,0 +1,11 @@
--- a/backport-include/linux/verification.h
+++ b/backport-include/linux/verification.h
@@ -1,7 +1,7 @@
#ifndef __BP_VERIFICATION_H
#define __BP_VERIFICATION_H
#include <linux/version.h>
-#ifndef CPTCFG_BPAUTO_BUILD_SYSTEM_DATA_VERIFICATION
+#if LINUX_VERSION_IS_GEQ(4,7,0) && !defined(CPTCFG_BPAUTO_BUILD_SYSTEM_DATA_VERIFICATION)
#include_next <linux/verification.h>
#else
#include <linux/key.h>

View file

@ -0,0 +1,10 @@
--- a/compat/backport-4.12.c
+++ b/compat/backport-4.12.c
@@ -224,6 +224,7 @@ int bp_extack_genl_register_family(struc
}
/* copy this since the family might access it directly */
+ family->id = copy->family.id;
family->attrbuf = copy->family.attrbuf;
family->mcgrp_offset = copy->family.mcgrp_offset;

View file

@ -0,0 +1,15 @@
--- a/backport-include/linux/rfkill.h
+++ b/backport-include/linux/rfkill.h
@@ -2,6 +2,12 @@
#define __COMPAT_RFKILL_H
#include <linux/version.h>
+#undef CONFIG_RFKILL
+#undef CONFIG_RFKILL_FULL
+#undef CONFIG_RFKILL_LEDS
+#undef CONFIG_RFKILL_MODULE
+#undef CONFIG_RFKILL_FULL_MODULE
+
#if LINUX_VERSION_IS_GEQ(3,10,0)
#include_next <linux/rfkill.h>
#else

View file

@ -0,0 +1,11 @@
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
# Makefile for the output source package
#
-ifeq ($(KERNELRELEASE),)
+ifeq ($(KERNELVERSION),)
MAKEFLAGS += --no-print-directory
SHELL := /usr/bin/env bash

View file

@ -0,0 +1,34 @@
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -11506,6 +11506,15 @@ static const struct attribute_group ipw_
.attrs = ipw_sysfs_entries,
};
+#if LINUX_VERSION_IS_LESS(4,10,0)
+static int __change_mtu(struct net_device *ndev, int new_mtu){
+ if (new_mtu < 68 || new_mtu > LIBIPW_DATA_LEN)
+ return -EINVAL;
+ ndev->mtu = new_mtu;
+ return 0;
+}
+#endif
+
#ifdef CPTCFG_IPW2200_PROMISCUOUS
static int ipw_prom_open(struct net_device *dev)
{
@@ -11554,15 +11563,6 @@ static netdev_tx_t ipw_prom_hard_start_x
return NETDEV_TX_OK;
}
-#if LINUX_VERSION_IS_LESS(4,10,0)
-static int __change_mtu(struct net_device *ndev, int new_mtu){
- if (new_mtu < 68 || new_mtu > LIBIPW_DATA_LEN)
- return -EINVAL;
- ndev->mtu = new_mtu;
- return 0;
-}
-#endif
-
static const struct net_device_ops ipw_prom_netdev_ops = {
#if LINUX_VERSION_IS_LESS(4,10,0)
.ndo_change_mtu = __change_mtu,

View file

@ -0,0 +1,47 @@
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
@@ -225,36 +225,37 @@ config RT2800SOC
config RT2800_LIB
- tristate
+ tristate "RT2800 USB/PCI support"
depends on m
config RT2800_LIB_MMIO
- tristate
+ tristate "RT2800 MMIO support"
depends on m
select RT2X00_LIB_MMIO
select RT2800_LIB
config RT2X00_LIB_MMIO
- tristate
+ tristate "RT2x00 MMIO support"
depends on m
config RT2X00_LIB_PCI
- tristate
+ tristate "RT2x00 PCI support"
depends on m
select RT2X00_LIB
config RT2X00_LIB_SOC
- tristate
+ tristate "RT2x00 SoC support"
+ depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
depends on m
select RT2X00_LIB
config RT2X00_LIB_USB
- tristate
+ tristate "RT2x00 USB support"
depends on m
select RT2X00_LIB
config RT2X00_LIB
- tristate
+ tristate "RT2x00 support"
depends on m
config RT2X00_LIB_FIRMWARE

View file

@ -0,0 +1,9 @@
--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
+++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
@@ -1,5 +1,5 @@
config BRCMUTIL
- tristate
+ tristate "Broadcom 802.11 driver utility functions"
depends on m
config BRCMSMAC

View file

@ -0,0 +1,30 @@
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -181,7 +181,7 @@ config CFG80211_WEXT_EXPORT
wext compatibility symbols to be exported.
config LIB80211
- tristate
+ tristate "lib80211"
depends on m
default n
help
@@ -191,15 +191,15 @@ config LIB80211
Drivers should select this themselves if needed.
config LIB80211_CRYPT_WEP
- tristate
+ tristate "lib80211 WEP support"
depends on m
config LIB80211_CRYPT_CCMP
- tristate
+ tristate "lib80211 CCMP support"
depends on m
config LIB80211_CRYPT_TKIP
- tristate
+ tristate "lib80211 TKIP support"
depends on m
config LIB80211_DEBUG

View file

@ -0,0 +1,132 @@
--- a/local-symbols
+++ b/local-symbols
@@ -388,45 +388,6 @@ USB_IPHETH=
USB_SIERRA_NET=
USB_VL600=
USB_NET_CH9200=
-SSB_POSSIBLE=
-SSB=
-SSB_SPROM=
-SSB_BLOCKIO=
-SSB_PCIHOST_POSSIBLE=
-SSB_PCIHOST=
-SSB_B43_PCI_BRIDGE=
-SSB_PCMCIAHOST_POSSIBLE=
-SSB_PCMCIAHOST=
-SSB_SDIOHOST_POSSIBLE=
-SSB_SDIOHOST=
-SSB_HOST_SOC=
-SSB_SILENT=
-SSB_DEBUG=
-SSB_SERIAL=
-SSB_DRIVER_PCICORE_POSSIBLE=
-SSB_DRIVER_PCICORE=
-SSB_PCICORE_HOSTMODE=
-SSB_DRIVER_MIPS=
-SSB_SFLASH=
-SSB_EMBEDDED=
-SSB_DRIVER_EXTIF=
-SSB_DRIVER_GIGE=
-SSB_DRIVER_GPIO=
-BCMA_POSSIBLE=
-BCMA=
-BCMA_BLOCKIO=
-BCMA_HOST_PCI_POSSIBLE=
-BCMA_HOST_PCI=
-BCMA_HOST_SOC=
-BCMA_DRIVER_PCI=
-BCMA_DRIVER_PCI_HOSTMODE=
-BCMA_DRIVER_MIPS=
-BCMA_PFLASH=
-BCMA_SFLASH=
-BCMA_NFLASH=
-BCMA_DRIVER_GMAC_CMN=
-BCMA_DRIVER_GPIO=
-BCMA_DEBUG=
NFC=
NFC_DIGITAL=
NFC_NCI=
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -2876,7 +2876,7 @@ static struct ssb_device *b43_ssb_gpio_d
{
struct ssb_bus *bus = dev->dev->sdev->bus;
-#ifdef CPTCFG_SSB_DRIVER_PCICORE
+#ifdef CONFIG_SSB_DRIVER_PCICORE
return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
#else
return bus->chipco.dev;
@@ -4893,7 +4893,7 @@ static int b43_wireless_core_init(struct
}
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
-#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE)
+#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
if (dev->dev->bus_type == B43_BUS_SSB &&
dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
@@ -1937,7 +1937,7 @@ static int b43legacy_gpio_init(struct b4
if (dev->dev->id.revision >= 2)
mask |= 0x0010; /* FIXME: This is redundant. */
-#ifdef CPTCFG_SSB_DRIVER_PCICORE
+#ifdef CONFIG_SSB_DRIVER_PCICORE
pcidev = bus->pcicore.dev;
#endif
gpiodev = bus->chipco.dev ? : pcidev;
@@ -1956,7 +1956,7 @@ static void b43legacy_gpio_cleanup(struc
struct ssb_bus *bus = dev->dev->bus;
struct ssb_device *gpiodev, *pcidev = NULL;
-#ifdef CPTCFG_SSB_DRIVER_PCICORE
+#ifdef CONFIG_SSB_DRIVER_PCICORE
pcidev = bus->pcicore.dev;
#endif
gpiodev = bus->chipco.dev ? : pcidev;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
@@ -42,6 +42,6 @@ brcmsmac-y := \
brcms_trace_events.o \
debug.o
-brcmsmac-$(CPTCFG_BCMA_DRIVER_GPIO) += led.o
+brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
obj-$(CPTCFG_BRCMSMAC) += brcmsmac.o
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
@@ -22,7 +22,7 @@ struct brcms_led {
bool active_low;
};
-#ifdef CPTCFG_BCMA_DRIVER_GPIO
+#ifdef CONFIG_BCMA_DRIVER_GPIO
void brcms_led_unregister(struct brcms_info *wl);
int brcms_led_register(struct brcms_info *wl);
#else
--- a/Kconfig.sources
+++ b/Kconfig.sources
@@ -9,9 +9,6 @@ source "$BACKPORT_DIR/drivers/net/wirele
#source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig"
source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
-source "$BACKPORT_DIR/drivers/ssb/Kconfig"
-source "$BACKPORT_DIR/drivers/bcma/Kconfig"
-
source "$BACKPORT_DIR/net/nfc/Kconfig"
#source "$BACKPORT_DIR/drivers/media/Kconfig"
--- a/Makefile.kernel
+++ b/Makefile.kernel
@@ -42,8 +42,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/
obj-$(CPTCFG_WLAN) += drivers/net/wireless/
#obj-$(CPTCFG_BT) += net/bluetooth/
#obj-$(CPTCFG_BT) += drivers/bluetooth/
-obj-$(CPTCFG_SSB) += drivers/ssb/
-obj-$(CPTCFG_BCMA) += drivers/bcma/
#obj-$(CPTCFG_ETHERNET) += drivers/net/ethernet/
obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/
obj-$(CPTCFG_NFC) += net/nfc/

View file

@ -0,0 +1,9 @@
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -1,5 +1,5 @@
config ATH_COMMON
- tristate
+ tristate "ath.ko"
depends on m
config WLAN_VENDOR_ATH

View file

@ -0,0 +1,47 @@
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -65,6 +65,12 @@ config ATH10K_TRACING
---help---
Select this to ath10k use tracing infrastructure.
+config ATH10K_THERMAL
+ bool "Atheros ath10k thermal monitoring support"
+ depends on THERMAL
+ ---help---
+ Select this to ath10k use hwmon for thermal measurement.
+
config ATH10K_DFS_CERTIFIED
bool "Atheros DFS support for certified platforms"
depends on ATH10K && CFG80211_CERTIFICATION_ONUS
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -17,7 +17,7 @@ ath10k_core-y += mac.o \
ath10k_core-$(CPTCFG_ATH10K_DEBUGFS) += spectral.o
ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o
ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
-ath10k_core-$(CONFIG_THERMAL) += thermal.o
+ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o
ath10k_core-$(CONFIG_PM) += wow.o
--- a/drivers/net/wireless/ath/ath10k/thermal.h
+++ b/drivers/net/wireless/ath/ath10k/thermal.h
@@ -36,7 +36,7 @@ struct ath10k_thermal {
int temperature;
};
-#if IS_REACHABLE(CONFIG_THERMAL)
+#if IS_REACHABLE(CPTCFG_ATH10K_THERMAL)
int ath10k_thermal_register(struct ath10k *ar);
void ath10k_thermal_unregister(struct ath10k *ar);
void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
--- a/local-symbols
+++ b/local-symbols
@@ -139,6 +139,7 @@ ATH10K_SDIO=
ATH10K_USB=
ATH10K_DEBUG=
ATH10K_DEBUGFS=
+ATH10K_THERMAL=
ATH10K_TRACING=
ATH10K_DFS_CERTIFIED=
WCN36XX=

View file

@ -0,0 +1,111 @@
From d06f26c5c8a41f246a9c40862a77a55725cedbd3 Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <sven.eckelmann@openmesh.com>
Date: Fri, 8 Dec 2017 11:37:42 +0100
Subject: ath10k: search DT for qcom,ath10k-calibration-variant
Board Data File (BDF) is loaded upon driver boot-up procedure. The right
board data file is identified on QCA4019 using bus, bmi-chip-id and
bmi-board-id.
The problem, however, can occur when the (default) board data file cannot
fulfill with the vendor requirements and it is necessary to use a different
board data file.
This problem was solved for SMBIOS by adding a special SMBIOS type 0xF8.
Something similar has to be provided for systems without SMBIOS but with
device trees. No solution was specified by QCA and therefore a new one has
to be found for ath10k.
The device tree requires addition strings to define the variant name
wifi@a000000 {
status = "okay";
qcom,ath10k-calibration-variant = "RT-AC58U";
};
wifi@a800000 {
status = "okay";
qcom,ath10k-calibration-variant = "RT-AC58U";
};
This would create the boarddata identifiers for the board-2.bin search
* bus=ahb,bmi-chip-id=0,bmi-board-id=16,variant=RT-AC58U
* bus=ahb,bmi-chip-id=0,bmi-board-id=17,variant=RT-AC58U
Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/core.c | 40 ++++++++++++++++++++++++++++------
1 file changed, 33 insertions(+), 7 deletions(-)
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -860,6 +860,28 @@ static int ath10k_core_check_smbios(stru
return 0;
}
+static int ath10k_core_check_dt(struct ath10k *ar)
+{
+ struct device_node *node;
+ const char *variant = NULL;
+
+ node = ar->dev->of_node;
+ if (!node)
+ return -ENOENT;
+
+ of_property_read_string(node, "qcom,ath10k-calibration-variant",
+ &variant);
+ if (!variant)
+ return -ENODATA;
+
+ if (strscpy(ar->id.bdf_ext, variant, sizeof(ar->id.bdf_ext)) < 0)
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
+ variant);
+
+ return 0;
+}
+
static int ath10k_download_and_run_otp(struct ath10k *ar)
{
u32 result, address = ar->hw_params.patch_load_addr;
@@ -1231,19 +1253,19 @@ static int ath10k_core_create_board_name
/* strlen(',variant=') + strlen(ar->id.bdf_ext) */
char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };
+ if (ar->id.bdf_ext[0] != '\0')
+ scnprintf(variant, sizeof(variant), ",variant=%s",
+ ar->id.bdf_ext);
+
if (ar->id.bmi_ids_valid) {
scnprintf(name, name_len,
- "bus=%s,bmi-chip-id=%d,bmi-board-id=%d",
+ "bus=%s,bmi-chip-id=%d,bmi-board-id=%d%s",
ath10k_bus_str(ar->hif.bus),
ar->id.bmi_chip_id,
- ar->id.bmi_board_id);
+ ar->id.bmi_board_id, variant);
goto out;
}
- if (ar->id.bdf_ext[0] != '\0')
- scnprintf(variant, sizeof(variant), ",variant=%s",
- ar->id.bdf_ext);
-
scnprintf(name, name_len,
"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
ath10k_bus_str(ar->hif.bus),
@@ -2343,7 +2365,11 @@ static int ath10k_core_probe_fw(struct a
ret = ath10k_core_check_smbios(ar);
if (ret)
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not set.\n");
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "SMBIOS bdf variant name not set.\n");
+
+ ret = ath10k_core_check_dt(ar);
+ if (ret)
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "DT bdf variant name not set.\n");
ret = ath10k_core_fetch_board_file(ar);
if (ret) {

View file

@ -0,0 +1,36 @@
From 606204bb863fa3b0bb54929d79b4dc46338f9180 Mon Sep 17 00:00:00 2001
From: Sathishkumar Muruganandam <murugana@codeaurora.org>
Date: Tue, 27 Mar 2018 11:26:46 +0300
Subject: [PATCH] ath10k: suppress "Unknown eventid: 36925" warnings
FW has Smart Logging feature enabled by default for detecting failures
and processing FATAL_CONDITION_EVENTID (36925 - 0x903D) back to host.
Since ath10k doesn't implement the Smart Logging and FATAL CONDITION
EVENT processing yet, suppressing the unknown event ID warning by moving
this under ATH10K_DBG_WMI.
Simulated the same issue by having associated STA powered off when
ping flood was running from AP backbone. This triggerd STA KICKOUT
in AP followed by FATAL CONDITION event 36925.
Issue was reproduced and verified in below DUT
------------------------------------------------
AP mode of OpenWRT QCA9984 running 6.0.8 with FW ver 10.4-3.5.3-00053
Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/ath/ath10k/wmi.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -5462,6 +5462,7 @@ static void ath10k_wmi_10_4_op_rx(struct
case WMI_10_4_WOW_WAKEUP_HOST_EVENTID:
case WMI_10_4_PEER_RATECODE_LIST_EVENTID:
case WMI_10_4_WDS_PEER_EVENTID:
+ case WMI_10_4_DEBUG_FATAL_CONDITION_EVENTID:
ath10k_dbg(ar, ATH10K_DBG_WMI,
"received event id %d not implemented\n", id);
break;

View file

@ -0,0 +1,45 @@
From patchwork Mon May 28 11:25:06 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Revert "rt2800: use TXOP_BACKOFF for probe frames"
From: Stanislaw Gruszka <sgruszka@redhat.com>
X-Patchwork-Id: 10431861
Message-Id: <1527506706-6488-1-git-send-email-sgruszka@redhat.com>
To: linux-wireless@vger.kernel.org
Date: Mon, 28 May 2018 13:25:06 +0200
This reverts commit fb47ada8dc3c30c8e7b415da155742b49536c61e.
In some situations when we set TXOP_BACKOFF, the probe frame is
not sent at all. What it worse then sending probe frame as part
of AMPDU and can degrade 11n performance to 11g rates.
Cc: stable@vger.kernel.org
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
@@ -372,16 +372,15 @@ static void rt2x00queue_create_tx_descri
/*
* Determine IFS values
- * - Use TXOP_BACKOFF for probe and management frames except beacons
+ * - Use TXOP_BACKOFF for management frames except beacons
* - Use TXOP_SIFS for fragment bursts
* - Use TXOP_HTTXOP for everything else
*
* Note: rt2800 devices won't use CTS protection (if used)
* for frames not transmitted with TXOP_HTTXOP
*/
- if ((ieee80211_is_mgmt(hdr->frame_control) &&
- !ieee80211_is_beacon(hdr->frame_control)) ||
- (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
+ if (ieee80211_is_mgmt(hdr->frame_control) &&
+ !ieee80211_is_beacon(hdr->frame_control))
txdesc->u.ht.txop = TXOP_BACKOFF;
else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
txdesc->u.ht.txop = TXOP_SIFS;

View file

@ -0,0 +1,705 @@
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -6,7 +6,6 @@ mac80211-y := \
driver-ops.o \
sta_info.o \
wep.o \
- aead_api.o \
wpa.o \
scan.o offchannel.o \
ht.o agg-tx.o agg-rx.o \
@@ -16,8 +15,8 @@ mac80211-y := \
rate.o \
michael.o \
tkip.o \
+ aes_ccm.o \
aes_cmac.o \
- aes_gmac.o \
fils_aead.o \
cfg.o \
ethtool.o \
--- a/net/mac80211/aead_api.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2003-2004, Instant802 Networks, Inc.
- * Copyright 2005-2006, Devicescape Software, Inc.
- * Copyright 2014-2015, Qualcomm Atheros, Inc.
- *
- * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/scatterlist.h>
-#include <crypto/aead.h>
-
-#include "aead_api.h"
-
-int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
- u8 *data, size_t data_len, u8 *mic)
-{
- size_t mic_len = crypto_aead_authsize(tfm);
- struct scatterlist sg[3];
- struct aead_request *aead_req;
- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
- u8 *__aad;
-
- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
- if (!aead_req)
- return -ENOMEM;
-
- __aad = (u8 *)aead_req + reqsize;
- memcpy(__aad, aad, aad_len);
-
- sg_init_table(sg, 3);
- sg_set_buf(&sg[0], __aad, aad_len);
- sg_set_buf(&sg[1], data, data_len);
- sg_set_buf(&sg[2], mic, mic_len);
-
- aead_request_set_tfm(aead_req, tfm);
- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
- aead_request_set_ad(aead_req, sg[0].length);
-
- crypto_aead_encrypt(aead_req);
- kzfree(aead_req);
-
- return 0;
-}
-
-int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
- u8 *data, size_t data_len, u8 *mic)
-{
- size_t mic_len = crypto_aead_authsize(tfm);
- struct scatterlist sg[3];
- struct aead_request *aead_req;
- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
- u8 *__aad;
- int err;
-
- if (data_len == 0)
- return -EINVAL;
-
- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
- if (!aead_req)
- return -ENOMEM;
-
- __aad = (u8 *)aead_req + reqsize;
- memcpy(__aad, aad, aad_len);
-
- sg_init_table(sg, 3);
- sg_set_buf(&sg[0], __aad, aad_len);
- sg_set_buf(&sg[1], data, data_len);
- sg_set_buf(&sg[2], mic, mic_len);
-
- aead_request_set_tfm(aead_req, tfm);
- aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
- aead_request_set_ad(aead_req, sg[0].length);
-
- err = crypto_aead_decrypt(aead_req);
- kzfree(aead_req);
-
- return err;
-}
-
-struct crypto_aead *
-aead_key_setup_encrypt(const char *alg, const u8 key[],
- size_t key_len, size_t mic_len)
-{
- struct crypto_aead *tfm;
- int err;
-
- tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- return tfm;
-
- err = crypto_aead_setkey(tfm, key, key_len);
- if (err)
- goto free_aead;
- err = crypto_aead_setauthsize(tfm, mic_len);
- if (err)
- goto free_aead;
-
- return tfm;
-
-free_aead:
- crypto_free_aead(tfm);
- return ERR_PTR(err);
-}
-
-void aead_key_free(struct crypto_aead *tfm)
-{
- crypto_free_aead(tfm);
-}
--- a/net/mac80211/aead_api.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _AEAD_API_H
-#define _AEAD_API_H
-
-#include <crypto/aead.h>
-#include <linux/crypto.h>
-
-struct crypto_aead *
-aead_key_setup_encrypt(const char *alg, const u8 key[],
- size_t key_len, size_t mic_len);
-
-int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
- size_t aad_len, u8 *data,
- size_t data_len, u8 *mic);
-
-int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
- size_t aad_len, u8 *data,
- size_t data_len, u8 *mic);
-
-void aead_key_free(struct crypto_aead *tfm);
-
-#endif /* _AEAD_API_H */
--- a/net/mac80211/aes_ccm.h
+++ b/net/mac80211/aes_ccm.h
@@ -10,39 +10,17 @@
#ifndef AES_CCM_H
#define AES_CCM_H
-#include "aead_api.h"
+#include <linux/crypto.h>
-#define CCM_AAD_LEN 32
-
-static inline struct crypto_aead *
-ieee80211_aes_key_setup_encrypt(const u8 key[], size_t key_len, size_t mic_len)
-{
- return aead_key_setup_encrypt("ccm(aes)", key, key_len, mic_len);
-}
-
-static inline int
-ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm,
- u8 *b_0, u8 *aad, u8 *data,
- size_t data_len, u8 *mic)
-{
- return aead_encrypt(tfm, b_0, aad + 2,
- be16_to_cpup((__be16 *)aad),
- data, data_len, mic);
-}
-
-static inline int
-ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm,
- u8 *b_0, u8 *aad, u8 *data,
- size_t data_len, u8 *mic)
-{
- return aead_decrypt(tfm, b_0, aad + 2,
- be16_to_cpup((__be16 *)aad),
- data, data_len, mic);
-}
-
-static inline void ieee80211_aes_key_free(struct crypto_aead *tfm)
-{
- return aead_key_free(tfm);
-}
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
+ size_t key_len,
+ size_t mic_len);
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic,
+ size_t mic_len);
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic,
+ size_t mic_len);
+void ieee80211_aes_key_free(struct crypto_cipher *tfm);
#endif /* AES_CCM_H */
--- /dev/null
+++ b/net/mac80211/aes_gcm.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2014-2015, Qualcomm Atheros, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <crypto/aead.h>
+
+#include <net/mac80211.h>
+#include "key.h"
+#include "aes_gcm.h"
+
+int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic)
+{
+ struct scatterlist sg[3];
+ struct aead_request *aead_req;
+ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+ u8 *__aad;
+
+ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
+ if (!aead_req)
+ return -ENOMEM;
+
+ __aad = (u8 *)aead_req + reqsize;
+ memcpy(__aad, aad, GCM_AAD_LEN);
+
+ sg_init_table(sg, 3);
+ sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
+ sg_set_buf(&sg[1], data, data_len);
+ sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
+
+ aead_request_set_tfm(aead_req, tfm);
+ aead_request_set_crypt(aead_req, sg, sg, data_len, j_0);
+ aead_request_set_ad(aead_req, sg[0].length);
+
+ crypto_aead_encrypt(aead_req);
+ kzfree(aead_req);
+ return 0;
+}
+
+int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic)
+{
+ struct scatterlist sg[3];
+ struct aead_request *aead_req;
+ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+ u8 *__aad;
+ int err;
+
+ if (data_len == 0)
+ return -EINVAL;
+
+ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
+ if (!aead_req)
+ return -ENOMEM;
+
+ __aad = (u8 *)aead_req + reqsize;
+ memcpy(__aad, aad, GCM_AAD_LEN);
+
+ sg_init_table(sg, 3);
+ sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
+ sg_set_buf(&sg[1], data, data_len);
+ sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
+
+ aead_request_set_tfm(aead_req, tfm);
+ aead_request_set_crypt(aead_req, sg, sg,
+ data_len + IEEE80211_GCMP_MIC_LEN, j_0);
+ aead_request_set_ad(aead_req, sg[0].length);
+
+ err = crypto_aead_decrypt(aead_req);
+ kzfree(aead_req);
+
+ return err;
+}
+
+struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
+ size_t key_len)
+{
+ struct crypto_aead *tfm;
+ int err;
+
+ tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm))
+ return tfm;
+
+ err = crypto_aead_setkey(tfm, key, key_len);
+ if (err)
+ goto free_aead;
+ err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN);
+ if (err)
+ goto free_aead;
+
+ return tfm;
+
+free_aead:
+ crypto_free_aead(tfm);
+ return ERR_PTR(err);
+}
+
+void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
+{
+ crypto_free_aead(tfm);
+}
--- a/net/mac80211/aes_gcm.h
+++ b/net/mac80211/aes_gcm.h
@@ -9,38 +9,30 @@
#ifndef AES_GCM_H
#define AES_GCM_H
-#include "aead_api.h"
+#include <linux/crypto.h>
-#define GCM_AAD_LEN 32
-
-static inline int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm,
- u8 *j_0, u8 *aad, u8 *data,
- size_t data_len, u8 *mic)
+static inline void
+ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic)
{
- return aead_encrypt(tfm, j_0, aad + 2,
- be16_to_cpup((__be16 *)aad),
- data, data_len, mic);
}
-static inline int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm,
- u8 *j_0, u8 *aad, u8 *data,
- size_t data_len, u8 *mic)
+static inline int
+ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic)
{
- return aead_decrypt(tfm, j_0, aad + 2,
- be16_to_cpup((__be16 *)aad),
- data, data_len, mic);
+ return -EOPNOTSUPP;
}
static inline struct crypto_aead *
ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len)
{
- return aead_key_setup_encrypt("gcm(aes)", key,
- key_len, IEEE80211_GCMP_MIC_LEN);
+ return NULL;
}
-static inline void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
+static inline void
+ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
{
- return aead_key_free(tfm);
}
#endif /* AES_GCM_H */
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -306,7 +306,8 @@ ieee80211_crypto_tkip_decrypt(struct iee
}
-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
+ u16 data_len)
{
__le16 mask_fc;
int a4_included, mgmt;
@@ -336,14 +337,8 @@ static void ccmp_special_blocks(struct s
else
qos_tid = 0;
- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
- * mode authentication are not allowed to collide, yet both are derived
- * from this vector b_0. We only set L := 1 here to indicate that the
- * data size can be represented in (L+1) bytes. The CCM layer will take
- * care of storing the data length in the top (L+1) bytes and setting
- * and clearing the other bits as is required to derive the two IVs.
- */
- b_0[0] = 0x1;
+ /* First block, b_0 */
+ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
/* Nonce: Nonce Flags | A2 | PN
* Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
@@ -351,6 +346,8 @@ static void ccmp_special_blocks(struct s
b_0[1] = qos_tid | (mgmt << 4);
memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
+ /* l(m) */
+ put_unaligned_be16(data_len, &b_0[14]);
/* AAD (extra authenticate-only data) / masked 802.11 header
* FC | A1 | A2 | A3 | SC | [A4] | [QC] */
@@ -407,7 +404,7 @@ static int ccmp_encrypt_skb(struct ieee8
u8 *pos;
u8 pn[6];
u64 pn64;
- u8 aad[CCM_AAD_LEN];
+ u8 aad[2 * AES_BLOCK_SIZE];
u8 b_0[AES_BLOCK_SIZE];
if (info->control.hw_key &&
@@ -462,9 +459,11 @@ static int ccmp_encrypt_skb(struct ieee8
return 0;
pos += IEEE80211_CCMP_HDR_LEN;
- ccmp_special_blocks(skb, pn, b_0, aad);
- return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
- skb_put(skb, mic_len));
+ ccmp_special_blocks(skb, pn, b_0, aad, len);
+ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+ skb_put(skb, mic_len), mic_len);
+
+ return 0;
}
@@ -537,13 +536,13 @@ ieee80211_crypto_ccmp_decrypt(struct iee
u8 aad[2 * AES_BLOCK_SIZE];
u8 b_0[AES_BLOCK_SIZE];
/* hardware didn't decrypt/verify MIC */
- ccmp_special_blocks(skb, pn, b_0, aad);
+ ccmp_special_blocks(skb, pn, b_0, aad, data_len);
if (ieee80211_aes_ccm_decrypt(
key->u.ccmp.tfm, b_0, aad,
skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
data_len,
- skb->data + skb->len - mic_len))
+ skb->data + skb->len - mic_len, mic_len))
return RX_DROP_UNUSABLE;
}
@@ -639,7 +638,7 @@ static int gcmp_encrypt_skb(struct ieee8
u8 *pos;
u8 pn[6];
u64 pn64;
- u8 aad[GCM_AAD_LEN];
+ u8 aad[2 * AES_BLOCK_SIZE];
u8 j_0[AES_BLOCK_SIZE];
if (info->control.hw_key &&
@@ -696,8 +695,10 @@ static int gcmp_encrypt_skb(struct ieee8
pos += IEEE80211_GCMP_HDR_LEN;
gcmp_special_blocks(skb, pn, j_0, aad);
- return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
- skb_put(skb, IEEE80211_GCMP_MIC_LEN));
+ ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
+ skb_put(skb, IEEE80211_GCMP_MIC_LEN));
+
+ return 0;
}
ieee80211_tx_result
@@ -1121,9 +1122,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct
struct ieee80211_key *key = tx->key;
struct ieee80211_mmie_16 *mmie;
struct ieee80211_hdr *hdr;
- u8 aad[GMAC_AAD_LEN];
+ u8 aad[20];
u64 pn64;
- u8 nonce[GMAC_NONCE_LEN];
+ u8 nonce[12];
if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
return TX_DROP;
@@ -1169,7 +1170,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_key *key = rx->key;
struct ieee80211_mmie_16 *mmie;
- u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN];
+ u8 aad[20], mic[16], ipn[6], nonce[12];
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
if (!ieee80211_is_mgmt(hdr->frame_control))
--- /dev/null
+++ b/net/mac80211/aes_ccm.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2003-2004, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ *
+ * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <crypto/aead.h>
+#include <crypto/aes.h>
+
+#include <net/mac80211.h>
+#include "key.h"
+#include "aes_ccm.h"
+
+static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0,
+ u8 *a, u8 *b)
+{
+ int i;
+
+ crypto_cipher_encrypt_one(tfm, b, b_0);
+
+ /* Extra Authenticate-only data (always two AES blocks) */
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
+ aad[i] ^= b[i];
+ crypto_cipher_encrypt_one(tfm, b, aad);
+
+ aad += AES_BLOCK_SIZE;
+
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
+ aad[i] ^= b[i];
+ crypto_cipher_encrypt_one(tfm, a, aad);
+
+ /* Mask out bits from auth-only-b_0 */
+ b_0[0] &= 0x07;
+
+ /* S_0 is used to encrypt T (= MIC) */
+ b_0[14] = 0;
+ b_0[15] = 0;
+ crypto_cipher_encrypt_one(tfm, s_0, b_0);
+}
+
+
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic,
+ size_t mic_len)
+{
+ int i, j, last_len, num_blocks;
+ u8 b[AES_BLOCK_SIZE];
+ u8 s_0[AES_BLOCK_SIZE];
+ u8 e[AES_BLOCK_SIZE];
+ u8 *pos, *cpos;
+
+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
+ last_len = data_len % AES_BLOCK_SIZE;
+ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b);
+
+ /* Process payload blocks */
+ pos = data;
+ cpos = data;
+ for (j = 1; j <= num_blocks; j++) {
+ int blen = (j == num_blocks && last_len) ?
+ last_len : AES_BLOCK_SIZE;
+
+ /* Authentication followed by encryption */
+ for (i = 0; i < blen; i++)
+ b[i] ^= pos[i];
+ crypto_cipher_encrypt_one(tfm, b, b);
+
+ b_0[14] = (j >> 8) & 0xff;
+ b_0[15] = j & 0xff;
+ crypto_cipher_encrypt_one(tfm, e, b_0);
+ for (i = 0; i < blen; i++)
+ *cpos++ = *pos++ ^ e[i];
+ }
+
+ for (i = 0; i < mic_len; i++)
+ mic[i] = b[i] ^ s_0[i];
+}
+
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic,
+ size_t mic_len)
+{
+ int i, j, last_len, num_blocks;
+ u8 *pos, *cpos;
+ u8 a[AES_BLOCK_SIZE];
+ u8 b[AES_BLOCK_SIZE];
+ u8 s_0[AES_BLOCK_SIZE];
+
+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
+ last_len = data_len % AES_BLOCK_SIZE;
+ aes_ccm_prepare(tfm, b_0, aad, s_0, a, b);
+
+ /* Process payload blocks */
+ cpos = data;
+ pos = data;
+ for (j = 1; j <= num_blocks; j++) {
+ int blen = (j == num_blocks && last_len) ?
+ last_len : AES_BLOCK_SIZE;
+
+ /* Decryption followed by authentication */
+ b_0[14] = (j >> 8) & 0xff;
+ b_0[15] = j & 0xff;
+ crypto_cipher_encrypt_one(tfm, b, b_0);
+ for (i = 0; i < blen; i++) {
+ *pos = *cpos++ ^ b[i];
+ a[i] ^= *pos++;
+ }
+ crypto_cipher_encrypt_one(tfm, a, a);
+ }
+
+ for (i = 0; i < mic_len; i++) {
+ if ((mic[i] ^ s_0[i]) != a[i])
+ return -1;
+ }
+
+ return 0;
+}
+
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
+ size_t key_len,
+ size_t mic_len)
+{
+ struct crypto_cipher *tfm;
+
+ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+ if (!IS_ERR(tfm))
+ crypto_cipher_setkey(tfm, key, key_len);
+
+ return tfm;
+}
+
+
+void ieee80211_aes_key_free(struct crypto_cipher *tfm)
+{
+ crypto_free_cipher(tfm);
+}
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -5,8 +5,6 @@ config MAC80211
depends on CRYPTO
depends on CRYPTO_ARC4
depends on CRYPTO_AES
- depends on CRYPTO_CCM
- depends on CRYPTO_GCM
depends on CRYPTO_CMAC
depends on CRC32
---help---
--- a/net/mac80211/aes_gmac.h
+++ b/net/mac80211/aes_gmac.h
@@ -15,10 +15,22 @@
#define GMAC_MIC_LEN 16
#define GMAC_NONCE_LEN 12
-struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
- size_t key_len);
-int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
- const u8 *data, size_t data_len, u8 *mic);
-void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm);
+static inline struct crypto_aead *
+ieee80211_aes_gmac_key_setup(const u8 key[], size_t key_len)
+{
+ return NULL;
+}
+
+static inline int
+ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
+ const u8 *data, size_t data_len, u8 *mic)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void
+ieee80211_aes_gmac_key_free(struct crypto_aead *tfm)
+{
+}
#endif /* AES_GMAC_H */
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -88,7 +88,7 @@ struct ieee80211_key {
* Management frames.
*/
u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
- struct crypto_aead *tfm;
+ struct crypto_cipher *tfm;
u32 replays; /* dot11RSNAStatsCCMPReplays */
} ccmp;
struct {

View file

@ -0,0 +1,12 @@
Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1058,7 +1058,6 @@ static int ieee80211_stop_ap(struct wiph
sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
__sta_info_flush(sdata, true);
- ieee80211_free_keys(sdata, true);
sdata->vif.bss_conf.enable_beacon = false;
sdata->vif.bss_conf.ssid_len = 0;

View file

@ -0,0 +1,43 @@
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -24,18 +24,35 @@ static inline struct cfg80211_registered
return container_of(dev, struct cfg80211_registered_device, wiphy.dev);
}
-#define SHOW_FMT(name, fmt, member) \
+#define SHOW_FMT(name, fmt, member, mode) \
static ssize_t name ## _show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
} \
-static DEVICE_ATTR_RO(name)
+static DEVICE_ATTR_##mode(name)
-SHOW_FMT(index, "%d", wiphy_idx);
-SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
-SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
+static ssize_t macaddress_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ u8 mac[ETH_ALEN];
+
+ if (!mac_pton(buf, mac))
+ return -EINVAL;
+
+ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
+ return -EINVAL;
+
+ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN);
+
+ return strnlen(buf, len);
+}
+
+SHOW_FMT(index, "%d", wiphy_idx, RO);
+SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW);
+SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO);
static ssize_t name_show(struct device *dev,
struct device_attribute *attr,

View file

@ -0,0 +1,32 @@
Disable FILS support, since it pulls in crypto hash support
--- a/net/mac80211/fils_aead.h
+++ b/net/mac80211/fils_aead.h
@@ -10,7 +10,7 @@
#ifndef FILS_AEAD_H
#define FILS_AEAD_H
-#if LINUX_VERSION_IS_GEQ(4,3,0)
+#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */
int fils_encrypt_assoc_req(struct sk_buff *skb,
struct ieee80211_mgd_assoc_data *assoc_data);
int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
--- a/net/mac80211/fils_aead.c
+++ b/net/mac80211/fils_aead.c
@@ -1,4 +1,4 @@
-#if LINUX_VERSION_IS_GEQ(4,3,0)
+#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */
/*
* FILS AEAD for (Re)Association Request/Response frames
* Copyright 2016, Qualcomm Atheros, Inc.
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -550,7 +550,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
NL80211_FEATURE_MAC_ON_CREATE |
NL80211_FEATURE_USERSPACE_MPM |
NL80211_FEATURE_FULL_AP_CLIENT_STATE;
-#if LINUX_VERSION_IS_GEQ(4,3,0)
+#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
#endif

View file

@ -0,0 +1,199 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 7 Oct 2017 09:37:28 +0200
Subject: [PATCH] Revert "mac80211: aes-cmac: switch to shash CMAC
driver"
This reverts commit 26717828b75dd5c46e97f7f4a9b937d038bb2852.
Reduces mac80211 dependencies for LEDE
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/aes_cmac.c
+++ b/net/mac80211/aes_cmac.c
@@ -22,50 +22,126 @@
#define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
#define AAD_LEN 20
-static const u8 zero[CMAC_TLEN_256];
-void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
- const u8 *data, size_t data_len, u8 *mic)
+void gf_mulx(u8 *pad)
+{
+ int i, carry;
+
+ carry = pad[0] & 0x80;
+ for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
+ pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
+ pad[AES_BLOCK_SIZE - 1] <<= 1;
+ if (carry)
+ pad[AES_BLOCK_SIZE - 1] ^= 0x87;
+}
+
+void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac,
+ size_t mac_len)
{
- SHASH_DESC_ON_STACK(desc, tfm);
- u8 out[AES_BLOCK_SIZE];
+ u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
+ const u8 *pos, *end;
+ size_t i, e, left, total_len;
+
+ memset(cbc, 0, AES_BLOCK_SIZE);
+
+ total_len = 0;
+ for (e = 0; e < num_elem; e++)
+ total_len += len[e];
+ left = total_len;
+
+ e = 0;
+ pos = addr[0];
+ end = pos + len[0];
+
+ while (left >= AES_BLOCK_SIZE) {
+ for (i = 0; i < AES_BLOCK_SIZE; i++) {
+ cbc[i] ^= *pos++;
+ if (pos >= end) {
+ e++;
+ pos = addr[e];
+ end = pos + len[e];
+ }
+ }
+ if (left > AES_BLOCK_SIZE)
+ crypto_cipher_encrypt_one(tfm, cbc, cbc);
+ left -= AES_BLOCK_SIZE;
+ }
+
+ memset(pad, 0, AES_BLOCK_SIZE);
+ crypto_cipher_encrypt_one(tfm, pad, pad);
+ gf_mulx(pad);
+
+ if (left || total_len == 0) {
+ for (i = 0; i < left; i++) {
+ cbc[i] ^= *pos++;
+ if (pos >= end) {
+ e++;
+ pos = addr[e];
+ end = pos + len[e];
+ }
+ }
+ cbc[left] ^= 0x80;
+ gf_mulx(pad);
+ }
+
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
+ pad[i] ^= cbc[i];
+ crypto_cipher_encrypt_one(tfm, pad, pad);
+ memcpy(mac, pad, mac_len);
+}
- desc->tfm = tfm;
- crypto_shash_init(desc);
- crypto_shash_update(desc, aad, AAD_LEN);
- crypto_shash_update(desc, data, data_len - CMAC_TLEN);
- crypto_shash_finup(desc, zero, CMAC_TLEN, out);
+void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
+ const u8 *data, size_t data_len, u8 *mic)
+{
+ const u8 *addr[3];
+ size_t len[3];
+ u8 zero[CMAC_TLEN];
+
+ memset(zero, 0, CMAC_TLEN);
+ addr[0] = aad;
+ len[0] = AAD_LEN;
+ addr[1] = data;
+ len[1] = data_len - CMAC_TLEN;
+ addr[2] = zero;
+ len[2] = CMAC_TLEN;
- memcpy(mic, out, CMAC_TLEN);
+ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN);
}
-void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
+void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
const u8 *data, size_t data_len, u8 *mic)
{
- SHASH_DESC_ON_STACK(desc, tfm);
+ const u8 *addr[3];
+ size_t len[3];
+ u8 zero[CMAC_TLEN_256];
+
+ memset(zero, 0, CMAC_TLEN_256);
+ addr[0] = aad;
+ len[0] = AAD_LEN;
+ addr[1] = data;
+ len[1] = data_len - CMAC_TLEN_256;
+ addr[2] = zero;
+ len[2] = CMAC_TLEN_256;
- desc->tfm = tfm;
-
- crypto_shash_init(desc);
- crypto_shash_update(desc, aad, AAD_LEN);
- crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
- crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
+ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256);
}
-struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
- size_t key_len)
+struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
+ size_t key_len)
{
- struct crypto_shash *tfm;
+ struct crypto_cipher *tfm;
- tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
+ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
if (!IS_ERR(tfm))
- crypto_shash_setkey(tfm, key, key_len);
+ crypto_cipher_setkey(tfm, key, key_len);
return tfm;
}
-void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm)
+
+void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm)
{
- crypto_free_shash(tfm);
+ crypto_free_cipher(tfm);
}
--- a/net/mac80211/aes_cmac.h
+++ b/net/mac80211/aes_cmac.h
@@ -10,14 +10,13 @@
#define AES_CMAC_H
#include <linux/crypto.h>
-#include <crypto/hash.h>
-struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
- size_t key_len);
-void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
+struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
+ size_t key_len);
+void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
const u8 *data, size_t data_len, u8 *mic);
-void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
+void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
const u8 *data, size_t data_len, u8 *mic);
-void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm);
+void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm);
#endif /* AES_CMAC_H */
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -93,7 +93,7 @@ struct ieee80211_key {
} ccmp;
struct {
u8 rx_pn[IEEE80211_CMAC_PN_LEN];
- struct crypto_shash *tfm;
+ struct crypto_cipher *tfm;
u32 replays; /* dot11RSNAStatsCMACReplays */
u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
} aes_cmac;

View file

@ -0,0 +1,10 @@
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -5,7 +5,6 @@ config MAC80211
depends on CRYPTO
depends on CRYPTO_ARC4
depends on CRYPTO_AES
- depends on CRYPTO_CMAC
depends on CRC32
---help---
This option enables the hardware independent IEEE 802.11

View file

@ -0,0 +1,15 @@
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3750,6 +3750,12 @@ out:
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
+#if defined(sk_pacing_shift) || LINUX_VERSION_IS_GEQ(4,15,0)
+ if (skb->sk && sk_fullsock(skb->sk) &&
+ skb->sk->sk_pacing_shift != 6)
+ skb->sk->sk_pacing_shift = 6;
+#endif
+
if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) {
struct sk_buff_head queue;

View file

@ -0,0 +1,67 @@
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -292,7 +292,7 @@ void ieee80211_restart_hw(struct ieee802
}
EXPORT_SYMBOL(ieee80211_restart_hw);
-#ifdef CONFIG_INET
+#ifdef __disabled__CONFIG_INET
static int ieee80211_ifa_changed(struct notifier_block *nb,
unsigned long data, void *arg)
{
@@ -351,7 +351,7 @@ static int ieee80211_ifa_changed(struct
}
#endif
-#if IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
static int ieee80211_ifa6_changed(struct notifier_block *nb,
unsigned long data, void *arg)
{
@@ -1114,14 +1114,14 @@ int ieee80211_register_hw(struct ieee802
if (result)
goto fail_flows;
-#ifdef CONFIG_INET
+#ifdef __disabled__CONFIG_INET
local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
result = register_inetaddr_notifier(&local->ifa_notifier);
if (result)
goto fail_ifa;
#endif
-#if IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
result = register_inet6addr_notifier(&local->ifa6_notifier);
if (result)
@@ -1130,13 +1130,13 @@ int ieee80211_register_hw(struct ieee802
return 0;
-#if IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
fail_ifa6:
-#ifdef CONFIG_INET
+#ifdef __disabled__CONFIG_INET
unregister_inetaddr_notifier(&local->ifa_notifier);
#endif
#endif
-#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
+#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6)
fail_ifa:
#endif
ieee80211_txq_teardown_flows(local);
@@ -1166,10 +1166,10 @@ void ieee80211_unregister_hw(struct ieee
tasklet_kill(&local->tx_pending_tasklet);
tasklet_kill(&local->tasklet);
-#ifdef CONFIG_INET
+#ifdef __disabled__CONFIG_INET
unregister_inetaddr_notifier(&local->ifa_notifier);
#endif
-#if IS_ENABLED(CONFIG_IPV6)
+#if IS_ENABLED(__disabled__CONFIG_IPV6)
unregister_inet6addr_notifier(&local->ifa6_notifier);
#endif

View file

@ -0,0 +1,237 @@
From: Thomas Hebb <tommyhebb@gmail.com>
Subject: [PATCH] ath10k: search all IEs for variant before falling back
Date: Wed, 21 Feb 2018 11:43:39 -0500
commit f2593cb1b291 ("ath10k: Search SMBIOS for OEM board file
extension") added a feature to ath10k that allows Board Data File
(BDF) conflicts between multiple devices that use the same device IDs
but have different calibration requirements to be resolved by allowing
a "variant" string to be stored in SMBIOS [and later device tree, added
by commit d06f26c5c8a4 ("ath10k: search DT for qcom,ath10k-calibration-
variant")] that gets appended to the ID stored in board-2.bin.
This original patch had a regression, however. Namely that devices with
a variant present in SMBIOS that didn't need custom BDFs could no longer
find the default BDF, which has no variant appended. The patch was
reverted and re-applied with a fix for this issue in commit 1657b8f84ed9
("search SMBIOS for OEM board file extension").
But the fix to fall back to a default BDF introduced another issue: the
driver currently parses IEs in board-2.bin one by one, and for each one
it first checks to see if it matches the ID with the variant appended.
If it doesn't, it checks to see if it matches the "fallback" ID with no
variant. If a matching BDF is found at any point during this search, the
search is terminated and that BDF is used. The issue is that it's very
possible (and is currently the case for board-2.bin files present in the
ath10k-firmware repository) for the default BDF to occur in an earlier
IE than the variant-specific BDF. In this case, the current code will
happily choose the default BDF even though a better-matching BDF is
present later in the file.
This patch fixes the issue by first searching the entire file for the ID
with variant, and searching for the fallback ID only if that search
fails. It also includes some code cleanup in the area, as
ath10k_core_fetch_board_data_api_n() no longer does its own string
mangling to remove the variant from an ID, instead leaving that job to a
new flag passed to ath10k_core_create_board_name().
I've tested this patch on a QCA4019 and verified that the driver behaves
correctly for 1) both fallback and variant BDFs present, 2) only fallback
BDF present, and 3) no matching BDFs present.
Fixes: 1657b8f84ed9 ("ath10k: search SMBIOS for OEM board file extension")
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
---
drivers/net/wireless/ath/ath10k/core.c | 134 ++++++++++++++++++---------------
1 file changed, 72 insertions(+), 62 deletions(-)
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1132,14 +1132,61 @@ out:
return ret;
}
+static int ath10k_core_search_bd(struct ath10k *ar,
+ const char *boardname,
+ const u8 *data,
+ size_t len)
+{
+ size_t ie_len;
+ struct ath10k_fw_ie *hdr;
+ int ret = -ENOENT, ie_id;
+
+ while (len > sizeof(struct ath10k_fw_ie)) {
+ hdr = (struct ath10k_fw_ie *)data;
+ ie_id = le32_to_cpu(hdr->id);
+ ie_len = le32_to_cpu(hdr->len);
+
+ len -= sizeof(*hdr);
+ data = hdr->data;
+
+ if (len < ALIGN(ie_len, 4)) {
+ ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n",
+ ie_id, ie_len, len);
+ return -EINVAL;
+ }
+
+ switch (ie_id) {
+ case ATH10K_BD_IE_BOARD:
+ ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
+ boardname);
+ if (ret == -ENOENT)
+ /* no match found, continue */
+ break;
+
+ /* either found or error, so stop searching */
+ goto out;
+ }
+
+ /* jump over the padding */
+ ie_len = ALIGN(ie_len, 4);
+
+ len -= ie_len;
+ data += ie_len;
+ }
+
+out:
+ /* return result of parse_bd_ie_board() or -ENOENT */
+ return ret;
+}
+
static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
const char *boardname,
+ const char *fallback_boardname,
const char *filename)
{
- size_t len, magic_len, ie_len;
- struct ath10k_fw_ie *hdr;
+ size_t len, magic_len;
const u8 *data;
- int ret, ie_id;
+ int ret;
ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
ar->hw_params.fw.dir,
@@ -1177,69 +1224,23 @@ static int ath10k_core_fetch_board_data_
data += magic_len;
len -= magic_len;
- while (len > sizeof(struct ath10k_fw_ie)) {
- hdr = (struct ath10k_fw_ie *)data;
- ie_id = le32_to_cpu(hdr->id);
- ie_len = le32_to_cpu(hdr->len);
-
- len -= sizeof(*hdr);
- data = hdr->data;
-
- if (len < ALIGN(ie_len, 4)) {
- ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n",
- ie_id, ie_len, len);
- ret = -EINVAL;
- goto err;
- }
+ /* attempt to find boardname in the IE list */
+ ret = ath10k_core_search_bd(ar, boardname, data, len);
- switch (ie_id) {
- case ATH10K_BD_IE_BOARD:
- ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
- boardname);
- if (ret == -ENOENT && ar->id.bdf_ext[0] != '\0') {
- /* try default bdf if variant was not found */
- char *s, *v = ",variant=";
- char boardname2[100];
-
- strlcpy(boardname2, boardname,
- sizeof(boardname2));
-
- s = strstr(boardname2, v);
- if (s)
- *s = '\0'; /* strip ",variant=%s" */
-
- ret = ath10k_core_parse_bd_ie_board(ar, data,
- ie_len,
- boardname2);
- }
+ /* if we didn't find it and have a fallback name, try that */
+ if (ret == -ENOENT && fallback_boardname)
+ ret = ath10k_core_search_bd(ar, fallback_boardname, data, len);
- if (ret == -ENOENT)
- /* no match found, continue */
- break;
- else if (ret)
- /* there was an error, bail out */
- goto err;
-
- /* board data found */
- goto out;
- }
-
- /* jump over the padding */
- ie_len = ALIGN(ie_len, 4);
-
- len -= ie_len;
- data += ie_len;
- }
-
-out:
- if (!ar->normal_mode_fw.board_data || !ar->normal_mode_fw.board_len) {
+ if (ret == -ENOENT) {
ath10k_err(ar,
"failed to fetch board data for %s from %s/%s\n",
boardname, ar->hw_params.fw.dir, filename);
ret = -ENODATA;
- goto err;
}
+ if (ret)
+ goto err;
+
return 0;
err:
@@ -1248,12 +1249,12 @@ err:
}
static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
- size_t name_len)
+ size_t name_len, bool with_variant)
{
/* strlen(',variant=') + strlen(ar->id.bdf_ext) */
char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };
- if (ar->id.bdf_ext[0] != '\0')
+ if (with_variant && ar->id.bdf_ext[0] != '\0')
scnprintf(variant, sizeof(variant), ",variant=%s",
ar->id.bdf_ext);
@@ -1279,17 +1280,26 @@ out:
static int ath10k_core_fetch_board_file(struct ath10k *ar)
{
- char boardname[100];
+ char boardname[100], fallback_boardname[100];
int ret;
- ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname));
+ ret = ath10k_core_create_board_name(ar, boardname,
+ sizeof(boardname), true);
if (ret) {
ath10k_err(ar, "failed to create board name: %d", ret);
return ret;
}
+ ret = ath10k_core_create_board_name(ar, fallback_boardname,
+ sizeof(boardname), false);
+ if (ret) {
+ ath10k_err(ar, "failed to create fallback board name: %d", ret);
+ return ret;
+ }
+
ar->bd_api = 2;
ret = ath10k_core_fetch_board_data_api_n(ar, boardname,
+ fallback_boardname,
ATH10K_BOARD_API2_FILE);
if (!ret)
goto success;

View file

@ -0,0 +1,38 @@
--- a/drivers/net/wireless/ath/ath5k/initvals.c
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini
{ AR5K_IMR, 0 },
{ AR5K_IER, AR5K_IER_DISABLE },
{ AR5K_BSR, 0, AR5K_INI_READ },
+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
{ AR5K_TXCFG, AR5K_DMASIZE_128B },
{ AR5K_RXCFG, AR5K_DMASIZE_128B },
+#else
+ /* WAR for AR71xx PCI bug */
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
+ { AR5K_RXCFG, AR5K_DMASIZE_4B },
+#endif
{ AR5K_CFG, AR5K_INIT_CFG },
{ AR5K_TOPS, 8 },
{ AR5K_RXNOFRM, 8 },
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
* guess we can tweak it and see how it goes ;-)
*/
if (ah->ah_version != AR5K_AR5210) {
+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
+#else
+ /* WAR for AR71xx PCI bug */
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
+#endif
}
/* Pre-enable interrupts on 5211/5212*/

View file

@ -0,0 +1,11 @@
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2215,7 +2215,7 @@ static int ieee80211_scan(struct wiphy *
* the frames sent while scanning on other channel will be
* lost)
*/
- if (sdata->u.ap.beacon &&
+ if (0 && sdata->u.ap.beacon &&
(!(wiphy->features & NL80211_FEATURE_AP_SCAN) ||
!(req->flags & NL80211_SCAN_FLAG_AP)))
return -EOPNOTSUPP;

View file

@ -0,0 +1,72 @@
From: Brian Norris <briannorris@chromium.org>
Date: Thu, 19 Oct 2017 11:45:19 -0700
Subject: [PATCH] ath10k: fix build errors with !CONFIG_PM
Build errors have been reported with CONFIG_PM=n:
drivers/net/wireless/ath/ath10k/pci.c:3416:8: error: implicit
declaration of function 'ath10k_pci_suspend'
[-Werror=implicit-function-declaration]
drivers/net/wireless/ath/ath10k/pci.c:3428:8: error: implicit
declaration of function 'ath10k_pci_resume'
[-Werror=implicit-function-declaration]
These are caused by the combination of the following two commits:
6af1de2e4ec4 ("ath10k: mark PM functions as __maybe_unused")
96378bd2c6cd ("ath10k: fix core PCI suspend when WoWLAN is supported but
disabled")
Both build fine on their own.
But now that ath10k_pci_pm_{suspend,resume}() is compiled
unconditionally, we should also compile ath10k_pci_{suspend,resume}()
unconditionally.
And drop the #ifdef around ath10k_pci_hif_{suspend,resume}() too; they
are trivial (empty), so we're not saving much space by compiling them
out. And the alternatives would be to sprinkle more __maybe_unused, or
spread the #ifdef's further.
Build tested with the following combinations:
CONFIG_PM=y && CONFIG_PM_SLEEP=y
CONFIG_PM=y && CONFIG_PM_SLEEP=n
CONFIG_PM=n
Fixes: 96378bd2c6cd ("ath10k: fix core PCI suspend when WoWLAN is supported but disabled")
Fixes: 096ad2a15fd8 ("Merge branch 'ath-next'")
Signed-off-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -2577,8 +2577,6 @@ void ath10k_pci_hif_power_down(struct at
*/
}
-#ifdef CONFIG_PM
-
static int ath10k_pci_hif_suspend(struct ath10k *ar)
{
/* Nothing to do; the important stuff is in the driver suspend. */
@@ -2627,7 +2625,6 @@ static int ath10k_pci_resume(struct ath1
return ret;
}
-#endif
static bool ath10k_pci_validate_cal(void *data, size_t size)
{
@@ -2782,10 +2779,8 @@ static const struct ath10k_hif_ops ath10
.power_down = ath10k_pci_hif_power_down,
.read32 = ath10k_pci_read32,
.write32 = ath10k_pci_write32,
-#ifdef CONFIG_PM
.suspend = ath10k_pci_hif_suspend,
.resume = ath10k_pci_hif_resume,
-#endif
.fetch_cal_eeprom = ath10k_pci_hif_fetch_cal_eeprom,
};

View file

@ -0,0 +1,37 @@
From: Johannes Berg <johannes.berg@intel.com>
Date: Mon, 20 Nov 2017 17:01:44 +0100
Subject: [PATCH] mac80211: properly free requested-but-not-started TX agg
sessions
When deleting a station or otherwise tearing down all aggregation
sessions, make sure to delete requested but not yet started ones,
to avoid the following scenario:
* session is requested, added to tid_start_tx[]
* ieee80211_ba_session_work() runs, gets past BLOCK_BA check
* ieee80211_sta_tear_down_BA_sessions() runs, locks &sta->ampdu_mlme.mtx,
e.g. while deleting the station - deleting all active sessions
* ieee80211_ba_session_work() continues since tear down flushes it, and
calls ieee80211_tx_ba_session_handle_start() for the new session, arms
the timer for it
* station deletion continues to __cleanup_single_sta() and frees the
session struct, while the timer is armed
Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -330,6 +330,11 @@ int ___ieee80211_stop_tx_ba_session(stru
spin_lock_bh(&sta->lock);
+ /* free struct pending for start, if present */
+ tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
+ kfree(tid_tx);
+ sta->ampdu_mlme.tid_start_tx[tid] = NULL;
+
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
if (!tid_tx) {
spin_unlock_bh(&sta->lock);

View file

@ -0,0 +1,25 @@
From: Johannes Berg <johannes.berg@intel.com>
Date: Thu, 4 Jan 2018 15:51:53 +0100
Subject: [PATCH] mac80211: mesh: drop frames appearing to be from us
If there are multiple mesh stations with the same MAC address,
they will both get confused and start throwing warnings.
Obviously in this case nothing can actually work anyway, so just
drop frames that look like they're from ourselves early on.
Reported-by: Gui Iribarren <gui@altermundi.net>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3632,6 +3632,8 @@ static bool ieee80211_accept_frame(struc
}
return true;
case NL80211_IFTYPE_MESH_POINT:
+ if (ether_addr_equal(sdata->vif.addr, hdr->addr2))
+ return false;
if (multicast)
return true;
return ether_addr_equal(sdata->vif.addr, hdr->addr1);

View file

@ -0,0 +1,60 @@
From 2fd3877b5bb7d39782c3205a1dcda02023b8514a Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Wed, 8 Nov 2017 14:36:31 +0100
Subject: [PATCH] brcmfmac: handle FWHALT mailbox indication
The firmware uses a mailbox to communicate to the host what is going
on. In the driver we validate the bit received. Various people seen
the following message:
brcmfmac: brcmf_sdio_hostmail: Unknown mailbox data content: 0x40012
Bit 4 is cause of this message, but this actually indicates the firmware
has halted. Handle this bit by giving a more meaningful error message.
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -260,10 +260,11 @@ struct rte_console {
#define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */
/* tohostmailboxdata */
-#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */
-#define HMB_DATA_DEVREADY 2 /* talk to host after enable */
-#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */
-#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */
+#define HMB_DATA_NAKHANDLED 0x0001 /* retransmit NAK'd frame */
+#define HMB_DATA_DEVREADY 0x0002 /* talk to host after enable */
+#define HMB_DATA_FC 0x0004 /* per prio flowcontrol update flag */
+#define HMB_DATA_FWREADY 0x0008 /* fw ready for protocol activity */
+#define HMB_DATA_FWHALT 0x0010 /* firmware halted */
#define HMB_DATA_FCDATA_MASK 0xff000000
#define HMB_DATA_FCDATA_SHIFT 24
@@ -1094,6 +1095,10 @@ static u32 brcmf_sdio_hostmail(struct br
offsetof(struct sdpcmd_regs, tosbmailbox));
bus->sdcnt.f1regdata += 2;
+ /* dongle indicates the firmware has halted/crashed */
+ if (hmb_data & HMB_DATA_FWHALT)
+ brcmf_err("mailbox indicates firmware halted\n");
+
/* Dongle recomposed rx frames, accept them again */
if (hmb_data & HMB_DATA_NAKHANDLED) {
brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n",
@@ -1151,6 +1156,7 @@ static u32 brcmf_sdio_hostmail(struct br
HMB_DATA_NAKHANDLED |
HMB_DATA_FC |
HMB_DATA_FWREADY |
+ HMB_DATA_FWHALT |
HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK))
brcmf_err("Unknown mailbox data content: 0x%02x\n",
hmb_data);

View file

@ -0,0 +1,133 @@
From 6c219b0088158da839a5be63c5b3d96c145501d2 Mon Sep 17 00:00:00 2001
From: Franky Lin <franky.lin@broadcom.com>
Date: Wed, 8 Nov 2017 14:36:32 +0100
Subject: [PATCH] brcmfmac: disable packet filtering in promiscuous mode
Disable arp and nd offload to allow all packets sending to host.
Reported-by: Phil Elwell <phil@raspberrypi.org>
Tested-by: Phil Elwell <phil@raspberrypi.org>
Reviewed-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 41 ----------------------
.../wireless/broadcom/brcm80211/brcmfmac/core.c | 38 ++++++++++++++++++++
.../wireless/broadcom/brcm80211/brcmfmac/core.h | 1 +
3 files changed, 39 insertions(+), 41 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -472,47 +472,6 @@ send_key_to_dongle(struct brcmf_if *ifp,
return err;
}
-static s32
-brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
-{
- s32 err;
- u32 mode;
-
- if (enable)
- mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
- else
- mode = 0;
-
- /* Try to set and enable ARP offload feature, this may fail, then it */
- /* is simply not supported and err 0 will be returned */
- err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode);
- if (err) {
- brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
- mode, err);
- err = 0;
- } else {
- err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable);
- if (err) {
- brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n",
- enable, err);
- err = 0;
- } else
- brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n",
- enable, mode);
- }
-
- err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable);
- if (err) {
- brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n",
- enable, err);
- err = 0;
- } else
- brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n",
- enable, mode);
-
- return err;
-}
-
static void
brcmf_cfg80211_update_proto_addr_mode(struct wireless_dev *wdev)
{
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -71,6 +71,43 @@ struct brcmf_if *brcmf_get_ifp(struct br
return ifp;
}
+void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
+{
+ s32 err;
+ u32 mode;
+
+ if (enable)
+ mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
+ else
+ mode = 0;
+
+ /* Try to set and enable ARP offload feature, this may fail, then it */
+ /* is simply not supported and err 0 will be returned */
+ err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode);
+ if (err) {
+ brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
+ mode, err);
+ } else {
+ err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable);
+ if (err) {
+ brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n",
+ enable, err);
+ } else {
+ brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n",
+ enable, mode);
+ }
+ }
+
+ err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable);
+ if (err) {
+ brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n",
+ enable, err);
+ } else {
+ brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n",
+ enable, mode);
+ }
+}
+
static void _brcmf_set_multicast_list(struct work_struct *work)
{
struct brcmf_if *ifp;
@@ -134,6 +171,7 @@ static void _brcmf_set_multicast_list(st
if (err < 0)
brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
err);
+ brcmf_configure_arp_nd_offload(ifp, !cmd_value);
}
#if IS_ENABLED(CONFIG_IPV6)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -203,6 +203,7 @@ int brcmf_netdev_wait_pend8021x(struct b
/* Return pointer to interface name */
char *brcmf_ifname(struct brcmf_if *ifp);
struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
+void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable);
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
bool is_p2pdev, const char *name, u8 *mac_addr);

View file

@ -0,0 +1,133 @@
From 8c6efda22f5f9f73fc948f517424466be01ae84d Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Wed, 8 Nov 2017 14:36:33 +0100
Subject: [PATCH] brcmfmac: cleanup brcmf_cfg80211_escan() function
The function brcmf_cfg80211_escan() was always called with a non-null
request parameter and null pointer for this_ssid parameter. Clean up
the function removing the dead code path.
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 76 ++++------------------
1 file changed, 11 insertions(+), 65 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -1072,18 +1072,10 @@ brcmf_do_escan(struct brcmf_if *ifp, str
static s32
brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
- struct cfg80211_scan_request *request,
- struct cfg80211_ssid *this_ssid)
+ struct cfg80211_scan_request *request)
{
- struct brcmf_if *ifp = vif->ifp;
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct cfg80211_ssid *ssids;
- u32 passive_scan;
- bool escan_req;
- bool spec_scan;
s32 err;
- struct brcmf_ssid_le ssid_le;
- u32 SSID_len;
brcmf_dbg(SCAN, "START ESCAN\n");
@@ -1101,8 +1093,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
cfg->scan_status);
return -EAGAIN;
}
- if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
- brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state);
+ if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) {
+ brcmf_err("Connecting: status (%lu)\n", vif->sme_state);
return -EAGAIN;
}
@@ -1110,63 +1102,17 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
- escan_req = false;
- if (request) {
- /* scan bss */
- ssids = request->ssids;
- escan_req = true;
- } else {
- /* scan in ibss */
- /* we don't do escan in ibss */
- ssids = this_ssid;
- }
-
cfg->scan_request = request;
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
- if (escan_req) {
- cfg->escan_info.run = brcmf_run_escan;
- err = brcmf_p2p_scan_prep(wiphy, request, vif);
- if (err)
- goto scan_out;
-
- err = brcmf_do_escan(vif->ifp, request);
- if (err)
- goto scan_out;
- } else {
- brcmf_dbg(SCAN, "ssid \"%s\", ssid_len (%d)\n",
- ssids->ssid, ssids->ssid_len);
- memset(&ssid_le, 0, sizeof(ssid_le));
- SSID_len = min_t(u8, sizeof(ssid_le.SSID), ssids->ssid_len);
- ssid_le.SSID_len = cpu_to_le32(0);
- spec_scan = false;
- if (SSID_len) {
- memcpy(ssid_le.SSID, ssids->ssid, SSID_len);
- ssid_le.SSID_len = cpu_to_le32(SSID_len);
- spec_scan = true;
- } else
- brcmf_dbg(SCAN, "Broadcast scan\n");
-
- passive_scan = cfg->active_scan ? 0 : 1;
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
- passive_scan);
- if (err) {
- brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
- goto scan_out;
- }
- brcmf_scan_config_mpc(ifp, 0);
- err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, &ssid_le,
- sizeof(ssid_le));
- if (err) {
- if (err == -EBUSY)
- brcmf_dbg(INFO, "BUSY: scan for \"%s\" canceled\n",
- ssid_le.SSID);
- else
- brcmf_err("WLC_SCAN error (%d)\n", err);
-
- brcmf_scan_config_mpc(ifp, 1);
- goto scan_out;
- }
- }
+
+ cfg->escan_info.run = brcmf_run_escan;
+ err = brcmf_p2p_scan_prep(wiphy, request, vif);
+ if (err)
+ goto scan_out;
+
+ err = brcmf_do_escan(vif->ifp, request);
+ if (err)
+ goto scan_out;
/* Arm scan timeout timer */
mod_timer(&cfg->escan_timeout, jiffies +
@@ -1191,7 +1137,7 @@ brcmf_cfg80211_scan(struct wiphy *wiphy,
if (!check_vif_up(vif))
return -EIO;
- err = brcmf_cfg80211_escan(wiphy, vif, request, NULL);
+ err = brcmf_cfg80211_escan(wiphy, vif, request);
if (err)
brcmf_err("scan error (%d)\n", err);

View file

@ -0,0 +1,31 @@
From df2d8388bc96c0f29d27d121f2a4cd054f8b3900 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Wed, 8 Nov 2017 14:36:34 +0100
Subject: [PATCH] brcmfmac: use msecs_to_jiffies() instead of calculation using
HZ
Minor cleanup using provided macro to convert milliseconds interval
to jiffies in brcmf_cfg80211_escan().
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -1115,8 +1115,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
goto scan_out;
/* Arm scan timeout timer */
- mod_timer(&cfg->escan_timeout, jiffies +
- BRCMF_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
+ mod_timer(&cfg->escan_timeout,
+ jiffies + msecs_to_jiffies(BRCMF_ESCAN_TIMER_INTERVAL_MS));
return 0;

View file

@ -0,0 +1,83 @@
From 588378f15cff285ac81c929239ccba01d7f71d50 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Wed, 8 Nov 2017 14:36:35 +0100
Subject: [PATCH] brcmfmac: get rid of brcmf_cfg80211_escan() function
The function brcmf_cfg80211_escan() is only called by brcmf_cfg80211_scan()
so there is no reason to split in two function especially since the latter
does not do an awful lot.
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 34 +++++++---------------
1 file changed, 10 insertions(+), 24 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -1071,13 +1071,16 @@ brcmf_do_escan(struct brcmf_if *ifp, str
}
static s32
-brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
- struct cfg80211_scan_request *request)
+brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- s32 err;
+ struct brcmf_cfg80211_vif *vif;
+ s32 err = 0;
- brcmf_dbg(SCAN, "START ESCAN\n");
+ brcmf_dbg(TRACE, "Enter\n");
+ vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);
+ if (!check_vif_up(vif))
+ return -EIO;
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
@@ -1102,6 +1105,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
+ brcmf_dbg(SCAN, "START ESCAN\n");
+
cfg->scan_request = request;
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
@@ -1121,31 +1126,12 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
return 0;
scan_out:
+ brcmf_err("scan error (%d)\n", err);
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
cfg->scan_request = NULL;
return err;
}
-static s32
-brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
-{
- struct brcmf_cfg80211_vif *vif;
- s32 err = 0;
-
- brcmf_dbg(TRACE, "Enter\n");
- vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);
- if (!check_vif_up(vif))
- return -EIO;
-
- err = brcmf_cfg80211_escan(wiphy, vif, request);
-
- if (err)
- brcmf_err("scan error (%d)\n", err);
-
- brcmf_dbg(TRACE, "Exit\n");
- return err;
-}
-
static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
{
s32 err = 0;

View file

@ -0,0 +1,86 @@
From bbf35414cd23a9d7230bfd7046e1e2c26020e7eb Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Wed, 8 Nov 2017 14:36:36 +0100
Subject: [PATCH] brcmfmac: get rid of struct brcmf_cfg80211_info::active_scan
field
The field struct brcmf_cfg80211_info::active_scan is set to true upon
initializing the driver instance, but it is never changed so simply
get rid of it.
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 10 +---------
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h | 2 --
drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 5 +----
3 files changed, 2 insertions(+), 15 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -1043,7 +1043,6 @@ brcmf_do_escan(struct brcmf_if *ifp, str
{
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
s32 err;
- u32 passive_scan;
struct brcmf_scan_results *results;
struct escan_info *escan = &cfg->escan_info;
@@ -1051,13 +1050,7 @@ brcmf_do_escan(struct brcmf_if *ifp, str
escan->ifp = ifp;
escan->wiphy = cfg->wiphy;
escan->escan_state = WL_ESCAN_STATE_SCANNING;
- passive_scan = cfg->active_scan ? 0 : 1;
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
- passive_scan);
- if (err) {
- brcmf_err("error (%d)\n", err);
- return err;
- }
+
brcmf_scan_config_mpc(ifp, 0);
results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
results->version = 0;
@@ -5767,7 +5760,6 @@ static s32 wl_init_priv(struct brcmf_cfg
cfg->scan_request = NULL;
cfg->pwr_save = true;
- cfg->active_scan = true; /* we do active scan per default */
cfg->dongle_up = false; /* dongle is not up yet */
err = brcmf_init_priv_mem(cfg);
if (err)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -283,7 +283,6 @@ struct brcmf_cfg80211_wowl {
* @scan_status: scan activity on the dongle.
* @pub: common driver information.
* @channel: current channel.
- * @active_scan: current scan mode.
* @int_escan_map: bucket map for which internal e-scan is done.
* @ibss_starter: indicates this sta is ibss starter.
* @pwr_save: indicate whether dongle to support power save mode.
@@ -316,7 +315,6 @@ struct brcmf_cfg80211_info {
unsigned long scan_status;
struct brcmf_pub *pub;
u32 channel;
- bool active_scan;
u32 int_escan_map;
bool ibss_starter;
bool pwr_save;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -692,10 +692,7 @@ static s32 brcmf_p2p_escan(struct brcmf_
/* determine the scan engine parameters */
sparams->bss_type = DOT11_BSSTYPE_ANY;
- if (p2p->cfg->active_scan)
- sparams->scan_type = 0;
- else
- sparams->scan_type = 1;
+ sparams->scan_type = BRCMF_SCANTYPE_ACTIVE;
eth_broadcast_addr(sparams->bssid);
sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS);

View file

@ -0,0 +1,55 @@
From bd99a3013bdc00f8fc7534c657b39616792b4467 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Wed, 8 Nov 2017 14:36:37 +0100
Subject: [PATCH] brcmfmac: move configuration of probe request IEs
The configuration of the IEs for probe requests was done in a P2P
related function, which is not very obvious. Moving it to
.scan callback function, ie. brcmf_cfg80211_scan().
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +++++
drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 6 ++----
2 files changed, 7 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -1108,6 +1108,11 @@ brcmf_cfg80211_scan(struct wiphy *wiphy,
if (err)
goto scan_out;
+ err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
+ request->ie, request->ie_len);
+ if (err)
+ goto scan_out;
+
err = brcmf_do_escan(vif->ifp, request);
if (err)
goto scan_out;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -881,7 +881,7 @@ int brcmf_p2p_scan_prep(struct wiphy *wi
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_p2p_info *p2p = &cfg->p2p;
- int err = 0;
+ int err;
if (brcmf_p2p_scan_is_p2p_request(request)) {
/* find my listen channel */
@@ -904,9 +904,7 @@ int brcmf_p2p_scan_prep(struct wiphy *wi
/* override .run_escan() callback. */
cfg->escan_info.run = brcmf_p2p_run_escan;
}
- err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
- request->ie, request->ie_len);
- return err;
+ return 0;
}

View file

@ -0,0 +1,434 @@
From fdd0bd88ceaecf729db103ac8836af5805dd2dc1 Mon Sep 17 00:00:00 2001
From: Chung-Hsien Hsu <stanley.hsu@cypress.com>
Date: Fri, 10 Nov 2017 17:27:15 +0800
Subject: [PATCH] brcmfmac: add CLM download support
The firmware for brcmfmac devices includes information regarding
regulatory constraints. For certain devices this information is kept
separately in a binary form that needs to be downloaded to the device.
This patch adds support to download this so-called CLM blob file. It
uses the same naming scheme as the other firmware files with extension
of .clm_blob.
The CLM blob file is optional. If the file does not exist, the download
process will be bypassed. It will not affect the driver loading.
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++
.../wireless/broadcom/brcm80211/brcmfmac/common.c | 157 +++++++++++++++++++++
.../wireless/broadcom/brcm80211/brcmfmac/core.c | 2 +
.../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 +
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 ++++
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 19 +++
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 19 +++
.../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++
8 files changed, 258 insertions(+)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -71,6 +71,7 @@ struct brcmf_bus_dcmd {
* @wowl_config: specify if dongle is configured for wowl when going to suspend
* @get_ramsize: obtain size of device memory.
* @get_memdump: obtain device memory dump in provided buffer.
+ * @get_fwname: obtain firmware name.
*
* This structure provides an abstract interface towards the
* bus specific driver. For control messages to common driver
@@ -87,6 +88,8 @@ struct brcmf_bus_ops {
void (*wowl_config)(struct device *dev, bool enabled);
size_t (*get_ramsize)(struct device *dev);
int (*get_memdump)(struct device *dev, void *data, size_t len);
+ int (*get_fwname)(struct device *dev, uint chip, uint chiprev,
+ unsigned char *fw_name);
};
@@ -224,6 +227,13 @@ int brcmf_bus_get_memdump(struct brcmf_b
return bus->ops->get_memdump(bus->dev, data, len);
}
+static inline
+int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev,
+ unsigned char *fw_name)
+{
+ return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name);
+}
+
/*
* interface functions from common layer
*/
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -18,6 +18,7 @@
#include <linux/string.h>
#include <linux/netdevice.h>
#include <linux/module.h>
+#include <linux/firmware.h>
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include "core.h"
@@ -28,6 +29,7 @@
#include "tracepoint.h"
#include "common.h"
#include "of.h"
+#include "firmware.h"
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
@@ -104,12 +106,140 @@ void brcmf_c_set_joinpref_default(struct
brcmf_err("Set join_pref error (%d)\n", err);
}
+static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
+ struct brcmf_dload_data_le *dload_buf,
+ u32 len)
+{
+ s32 err;
+
+ flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT);
+ dload_buf->flag = cpu_to_le16(flag);
+ dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM);
+ dload_buf->len = cpu_to_le32(len);
+ dload_buf->crc = cpu_to_le32(0);
+ len = sizeof(*dload_buf) + len - 1;
+
+ err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len);
+
+ return err;
+}
+
+static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name)
+{
+ struct brcmf_bus *bus = ifp->drvr->bus_if;
+ struct brcmf_rev_info *ri = &ifp->drvr->revinfo;
+ u8 fw_name[BRCMF_FW_NAME_LEN];
+ u8 *ptr;
+ size_t len;
+ s32 err;
+
+ memset(fw_name, 0, BRCMF_FW_NAME_LEN);
+ err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name);
+ if (err) {
+ brcmf_err("get firmware name failed (%d)\n", err);
+ goto done;
+ }
+
+ /* generate CLM blob file name */
+ ptr = strrchr(fw_name, '.');
+ if (!ptr) {
+ err = -ENOENT;
+ goto done;
+ }
+
+ len = ptr - fw_name + 1;
+ if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) {
+ err = -E2BIG;
+ } else {
+ strlcpy(clm_name, fw_name, len);
+ strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN);
+ }
+done:
+ return err;
+}
+
+static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
+{
+ struct device *dev = ifp->drvr->bus_if->dev;
+ struct brcmf_dload_data_le *chunk_buf;
+ const struct firmware *clm = NULL;
+ u8 clm_name[BRCMF_FW_NAME_LEN];
+ u32 chunk_len;
+ u32 datalen;
+ u32 cumulative_len;
+ u16 dl_flag = DL_BEGIN;
+ u32 status;
+ s32 err;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ memset(clm_name, 0, BRCMF_FW_NAME_LEN);
+ err = brcmf_c_get_clm_name(ifp, clm_name);
+ if (err) {
+ brcmf_err("get CLM blob file name failed (%d)\n", err);
+ return err;
+ }
+
+ err = request_firmware(&clm, clm_name, dev);
+ if (err) {
+ if (err == -ENOENT) {
+ brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n");
+ return 0;
+ }
+ brcmf_err("request CLM blob file failed (%d)\n", err);
+ return err;
+ }
+
+ chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL);
+ if (!chunk_buf) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ datalen = clm->size;
+ cumulative_len = 0;
+ do {
+ if (datalen > MAX_CHUNK_LEN) {
+ chunk_len = MAX_CHUNK_LEN;
+ } else {
+ chunk_len = datalen;
+ dl_flag |= DL_END;
+ }
+ memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len);
+
+ err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len);
+
+ dl_flag &= ~DL_BEGIN;
+
+ cumulative_len += chunk_len;
+ datalen -= chunk_len;
+ } while ((datalen > 0) && (err == 0));
+
+ if (err) {
+ brcmf_err("clmload (%zu byte file) failed (%d); ",
+ clm->size, err);
+ /* Retrieve clmload_status and print */
+ err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status);
+ if (err)
+ brcmf_err("get clmload_status failed (%d)\n", err);
+ else
+ brcmf_dbg(INFO, "clmload_status=%d\n", status);
+ err = -EIO;
+ }
+
+ kfree(chunk_buf);
+done:
+ release_firmware(clm);
+ return err;
+}
+
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
{
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
u8 buf[BRCMF_DCMD_SMLEN];
struct brcmf_rev_info_le revinfo;
struct brcmf_rev_info *ri;
+ char *clmver;
char *ptr;
s32 err;
@@ -148,6 +278,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
}
ri->result = err;
+ /* Do any CLM downloading */
+ err = brcmf_c_process_clm_blob(ifp);
+ if (err < 0) {
+ brcmf_err("download CLM blob file failed, %d\n", err);
+ goto done;
+ }
+
/* query for 'ver' to get version info from firmware */
memset(buf, 0, sizeof(buf));
strcpy(buf, "ver");
@@ -167,6 +304,26 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
ptr = strrchr(buf, ' ') + 1;
strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
+ /* Query for 'clmver' to get CLM version info from firmware */
+ memset(buf, 0, sizeof(buf));
+ err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf));
+ if (err) {
+ brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err);
+ } else {
+ clmver = (char *)buf;
+ /* store CLM version for adding it to revinfo debugfs file */
+ memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver));
+
+ /* Replace all newline/linefeed characters with space
+ * character
+ */
+ ptr = clmver;
+ while ((ptr = strnchr(ptr, '\n', sizeof(buf))) != NULL)
+ *ptr = ' ';
+
+ brcmf_dbg(INFO, "CLM version = %s\n", clmver);
+ }
+
/* set mpc */
err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
if (err) {
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -1009,6 +1009,8 @@ static int brcmf_revinfo_read(struct seq
seq_printf(s, "anarev: %u\n", ri->anarev);
seq_printf(s, "nvramrev: %08x\n", ri->nvramrev);
+ seq_printf(s, "clmver: %s\n", bus_if->drvr->clmver);
+
return 0;
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -141,6 +141,8 @@ struct brcmf_pub {
struct notifier_block inetaddr_notifier;
struct notifier_block inet6addr_notifier;
struct brcmf_mp_device *settings;
+
+ u8 clmver[BRCMF_DCMD_SMLEN];
};
/* forward declarations */
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -155,6 +155,21 @@
#define BRCMF_MFP_CAPABLE 1
#define BRCMF_MFP_REQUIRED 2
+/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each
+ * ioctl. It is relatively small because firmware has small maximum size input
+ * playload restriction for ioctls.
+ */
+#define MAX_CHUNK_LEN 1400
+
+#define DLOAD_HANDLER_VER 1 /* Downloader version */
+#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */
+#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */
+
+#define DL_BEGIN 0x0002
+#define DL_END 0x0004
+
+#define DL_TYPE_CLM 2
+
/* join preference types for join_pref iovar */
enum brcmf_join_pref_types {
BRCMF_JOIN_PREF_RSSI = 1,
@@ -827,6 +842,22 @@ struct brcmf_pno_macaddr_le {
};
/**
+ * struct brcmf_dload_data_le - data passing to firmware for downloading
+ * @flag: flags related to download data.
+ * @dload_type: type of download data.
+ * @len: length in bytes of download data.
+ * @crc: crc of download data.
+ * @data: download data.
+ */
+struct brcmf_dload_data_le {
+ __le16 flag;
+ __le16 dload_type;
+ __le32 len;
+ __le32 crc;
+ u8 data[1];
+};
+
+/**
* struct brcmf_pno_bssid_le - bssid configuration for PNO scan.
*
* @bssid: BSS network identifier.
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -1350,6 +1350,24 @@ static int brcmf_pcie_get_memdump(struct
return 0;
}
+static int brcmf_pcie_get_fwname(struct device *dev, u32 chip, u32 chiprev,
+ u8 *fw_name)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
+ struct brcmf_pciedev_info *devinfo = buspub->devinfo;
+ int ret = 0;
+
+ if (devinfo->fw_name[0] != '\0')
+ strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
+ else
+ ret = brcmf_fw_map_chip_to_name(chip, chiprev,
+ brcmf_pcie_fwnames,
+ ARRAY_SIZE(brcmf_pcie_fwnames),
+ fw_name, NULL);
+
+ return ret;
+}
static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
.txdata = brcmf_pcie_tx,
@@ -1359,6 +1377,7 @@ static const struct brcmf_bus_ops brcmf_
.wowl_config = brcmf_pcie_wowl_config,
.get_ramsize = brcmf_pcie_get_ramsize,
.get_memdump = brcmf_pcie_get_memdump,
+ .get_fwname = brcmf_pcie_get_fwname,
};
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3985,6 +3985,24 @@ brcmf_sdio_watchdog(unsigned long data)
}
}
+static int brcmf_sdio_get_fwname(struct device *dev, u32 chip, u32 chiprev,
+ u8 *fw_name)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+ int ret = 0;
+
+ if (sdiodev->fw_name[0] != '\0')
+ strlcpy(fw_name, sdiodev->fw_name, BRCMF_FW_NAME_LEN);
+ else
+ ret = brcmf_fw_map_chip_to_name(chip, chiprev,
+ brcmf_sdio_fwnames,
+ ARRAY_SIZE(brcmf_sdio_fwnames),
+ fw_name, NULL);
+
+ return ret;
+}
+
static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.stop = brcmf_sdio_bus_stop,
.preinit = brcmf_sdio_bus_preinit,
@@ -3995,6 +4013,7 @@ static const struct brcmf_bus_ops brcmf_
.wowl_config = brcmf_sdio_wowl_config,
.get_ramsize = brcmf_sdio_bus_get_ramsize,
.get_memdump = brcmf_sdio_bus_get_memdump,
+ .get_fwname = brcmf_sdio_get_fwname,
};
static void brcmf_sdio_firmware_callback(struct device *dev, int err,
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -1128,12 +1128,30 @@ static void brcmf_usb_wowl_config(struct
device_set_wakeup_enable(devinfo->dev, false);
}
+static int brcmf_usb_get_fwname(struct device *dev, u32 chip, u32 chiprev,
+ u8 *fw_name)
+{
+ struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+ int ret = 0;
+
+ if (devinfo->fw_name[0] != '\0')
+ strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
+ else
+ ret = brcmf_fw_map_chip_to_name(chip, chiprev,
+ brcmf_usb_fwnames,
+ ARRAY_SIZE(brcmf_usb_fwnames),
+ fw_name, NULL);
+
+ return ret;
+}
+
static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
.txdata = brcmf_usb_tx,
.stop = brcmf_usb_down,
.txctl = brcmf_usb_tx_ctlpkt,
.rxctl = brcmf_usb_rx_ctlpkt,
.wowl_config = brcmf_usb_wowl_config,
+ .get_fwname = brcmf_usb_get_fwname,
};
static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)

View file

@ -0,0 +1,37 @@
From 5c3de777bdaf48bd0cfb43097c0d0fb85056cab7 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Sat, 25 Nov 2017 21:39:25 +0100
Subject: [PATCH] brcmfmac: change driver unbind order of the sdio function
devices
In the function brcmf_sdio_firmware_callback() the driver is
unbound from the sdio function devices in the error path.
However, the order in which it is done resulted in a use-after-free
issue (see brcmf_ops_sdio_remove() in bcmsdh.c). Hence change
the order and first unbind sdio function #2 device and then
unbind sdio function #1 device.
Cc: stable@vger.kernel.org # v4.12.x
Fixes: 7a51461fc2da ("brcmfmac: unbind all devices upon failure in firmware callback")
Reported-by: Stefan Wahren <stefan.wahren@i2se.com>
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -4121,8 +4121,8 @@ release:
sdio_release_host(sdiodev->func[1]);
fail:
brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
- device_release_driver(dev);
device_release_driver(&sdiodev->func[2]->dev);
+ device_release_driver(dev);
}
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)

View file

@ -0,0 +1,33 @@
From 51ef7925e10688c57186d438e784532e063492e4 Mon Sep 17 00:00:00 2001
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Thu, 23 Nov 2017 17:57:04 +0200
Subject: [PATCH] brcmfmac: Avoid build error with make W=1
When I run make W=1 on gcc (Debian 7.2.0-16) 7.2.0 I got an error for
the first run, all next ones are okay.
CC [M] drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.o
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:2078: error: Cannot parse struct or union!
scripts/Makefile.build:310: recipe for target 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.o' failed
Seems like something happened with W=1 and wrong kernel doc format.
As a quick fix remove dubious /** in the code.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -2070,7 +2070,7 @@ static int brcmf_sdio_txpkt_hdalign(stru
return head_pad;
}
-/**
+/*
* struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for
* bus layer usage.
*/

View file

@ -0,0 +1,40 @@
From cc124d5cc8d81985c3511892d7a6d546552ff754 Mon Sep 17 00:00:00 2001
From: Wright Feng <wright.feng@cypress.com>
Date: Tue, 16 Jan 2018 17:26:50 +0800
Subject: [PATCH] brcmfmac: fix CLM load error for legacy chips when user
helper is enabled
For legacy chips without CLM blob files, kernel with user helper function
returns -EAGAIN when we request_firmware(), and then driver got failed
when bringing up legacy chips. We expect the CLM blob file for legacy chip
is not existence in firmware path, but the -ENOENT error is transferred to
-EAGAIN in firmware_class.c with user helper.
Because of that, we continue with CLM data currently present in firmware
if getting error from doing request_firmware().
Cc: stable@vger.kernel.org # v4.15.y
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Wright Feng <wright.feng@cypress.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -182,12 +182,9 @@ static int brcmf_c_process_clm_blob(stru
err = request_firmware(&clm, clm_name, dev);
if (err) {
- if (err == -ENOENT) {
- brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n");
- return 0;
- }
- brcmf_err("request CLM blob file failed (%d)\n", err);
- return err;
+ brcmf_info("no clm_blob available(err=%d), device may have limited channels available\n",
+ err);
+ return 0;
}
chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL);

View file

@ -0,0 +1,103 @@
From 9df7ddc3ed25b7d3473f117a0680b9418adb5753 Mon Sep 17 00:00:00 2001
Message-Id: <9df7ddc3ed25b7d3473f117a0680b9418adb5753.1515610034.git.mschiffer@universe-factory.net>
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Mon, 27 Nov 2017 18:56:22 +0100
Subject: [PATCH 1/2] ath9k: move spectral scan support under a separate config
symbol
At the moment, spectral scan support, and with it RELAY, is always enabled
with ATH9K[_HTC]_DEBUGFS. Spectral scan support is currently the only user
of RELAY in ath9k, and it unconditionally reserves a relay channel.
Having debugfs support in ath9k is often useful even on very small embedded
routers, where we'd rather like to avoid the code size and RAM usage of the
relay support.
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/Kconfig | 14 ++++++++++----
drivers/net/wireless/ath/ath9k/Makefile | 4 ++--
drivers/net/wireless/ath/ath9k/common-spectral.h | 4 ++--
3 files changed, 14 insertions(+), 8 deletions(-)
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -64,13 +64,12 @@ config ATH9K_DEBUGFS
depends on ATH9K && DEBUG_FS
select MAC80211_DEBUGFS
select ATH9K_COMMON_DEBUG
- depends on RELAY
---help---
Say Y, if you need access to ath9k's statistics for
interrupts, rate control, etc.
- Also required for changing debug message flags at run time.
- As well as access to the FFT/spectral data and TX99.
+ Also required for changing debug message flags at run time and for
+ TX99.
config ATH9K_STATION_STATISTICS
bool "Detailed station statistics"
@@ -181,7 +180,6 @@ config ATH9K_HTC_DEBUGFS
bool "Atheros ath9k_htc debugging"
depends on ATH9K_HTC && DEBUG_FS
select ATH9K_COMMON_DEBUG
- depends on RELAY
---help---
Say Y, if you need access to ath9k_htc's statistics.
As well as access to the FFT/spectral data.
@@ -197,3 +195,11 @@ config ATH9K_HWRNG
Say Y, feeds the entropy directly from the WiFi driver to the input
pool.
+
+config ATH9K_COMMON_SPECTRAL
+ bool "Atheros ath9k/ath9k_htc spectral scan support"
+ depends on ATH9K_DEBUGFS || ATH9K_HTC_DEBUGFS
+ depends on RELAY
+ default n
+ ---help---
+ Say Y to enable access to the FFT/spectral data via debugfs.
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -61,8 +61,8 @@ ath9k_common-y:= common.o \
common-init.o \
common-beacon.o \
-ath9k_common-$(CPTCFG_ATH9K_COMMON_DEBUG) += common-debug.o \
- common-spectral.o
+ath9k_common-$(CPTCFG_ATH9K_COMMON_DEBUG) += common-debug.o
+ath9k_common-$(CPTCFG_ATH9K_COMMON_SPECTRAL) += common-spectral.o
ath9k_htc-y += htc_hst.o \
hif_usb.o \
--- a/drivers/net/wireless/ath/ath9k/common-spectral.h
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.h
@@ -151,7 +151,7 @@ static inline u8 spectral_bitmap_weight(
return bins[0] & 0x3f;
}
-#ifdef CPTCFG_ATH9K_COMMON_DEBUG
+#ifdef CPTCFG_ATH9K_COMMON_SPECTRAL
void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy);
void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv);
@@ -183,6 +183,6 @@ static inline int ath_cmn_process_fft(st
{
return 0;
}
-#endif /* CPTCFG_ATH9K_COMMON_DEBUG */
+#endif /* CPTCFG_ATH9K_COMMON_SPECTRAL */
#endif /* SPECTRAL_H */
--- a/local-symbols
+++ b/local-symbols
@@ -116,6 +116,7 @@ ATH9K_PCOEM=
ATH9K_HTC=
ATH9K_HTC_DEBUGFS=
ATH9K_HWRNG=
+ATH9K_COMMON_SPECTRAL=
CARL9170=
CARL9170_LEDS=
CARL9170_DEBUGFS=

View file

@ -0,0 +1,91 @@
From 42e01cb9cb109fb0bb4743f6c54d6aa67ac39b61 Mon Sep 17 00:00:00 2001
Message-Id: <42e01cb9cb109fb0bb4743f6c54d6aa67ac39b61.1515610034.git.mschiffer@universe-factory.net>
In-Reply-To: <9df7ddc3ed25b7d3473f117a0680b9418adb5753.1515610034.git.mschiffer@universe-factory.net>
References: <9df7ddc3ed25b7d3473f117a0680b9418adb5753.1515610034.git.mschiffer@universe-factory.net>
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Mon, 27 Nov 2017 18:56:23 +0100
Subject: [PATCH 2/2] ath10k: move spectral scan support under a separate
config symbol
At the moment, spectral scan support, and with it RELAY, is always enabled
with ATH10K_DEBUGFS. Spectral scan support is currently the only user of
RELAY in ath10k, and it unconditionally reserves a relay channel.
Having debugfs support in ath10k is often useful even on very small
embedded routers, where we'd rather like to avoid the code size and RAM
usage of the relay support. While ath10k-based devices usually have more
resources than ath9k-based ones, it makes sense to keep the configuration
symmetric to ath9k, so the same base kernel without RELAY can be used for
both ath9k and ath10k hardware.
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/Kconfig | 9 ++++++++-
drivers/net/wireless/ath/ath10k/Makefile | 2 +-
drivers/net/wireless/ath/ath10k/spectral.h | 4 ++--
3 files changed, 11 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -51,12 +51,19 @@ config ATH10K_DEBUG
config ATH10K_DEBUGFS
bool "Atheros ath10k debugfs support"
depends on ATH10K && DEBUG_FS
- depends on RELAY
---help---
Enabled debugfs support
If unsure, say Y to make it easier to debug problems.
+config ATH10K_SPECTRAL
+ bool "Atheros ath10k spectral scan support"
+ depends on ATH10K_DEBUGFS
+ depends on RELAY
+ default n
+ ---help---
+ Say Y to enable access to the FFT/spectral data via debugfs.
+
config ATH10K_TRACING
depends on !KERNEL_3_4
bool "Atheros ath10k tracing support"
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -14,7 +14,7 @@ ath10k_core-y += mac.o \
p2p.o \
swap.o
-ath10k_core-$(CPTCFG_ATH10K_DEBUGFS) += spectral.o
+ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += spectral.o
ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o
ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
--- a/drivers/net/wireless/ath/ath10k/spectral.h
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -44,7 +44,7 @@ enum ath10k_spectral_mode {
SPECTRAL_MANUAL,
};
-#ifdef CPTCFG_ATH10K_DEBUGFS
+#ifdef CPTCFG_ATH10K_SPECTRAL
int ath10k_spectral_process_fft(struct ath10k *ar,
struct wmi_phyerr_ev_arg *phyerr,
@@ -85,6 +85,6 @@ static inline void ath10k_spectral_destr
{
}
-#endif /* CPTCFG_ATH10K_DEBUGFS */
+#endif /* CPTCFG_ATH10K_SPECTRAL */
#endif /* SPECTRAL_H */
--- a/local-symbols
+++ b/local-symbols
@@ -140,6 +140,7 @@ ATH10K_SDIO=
ATH10K_USB=
ATH10K_DEBUG=
ATH10K_DEBUGFS=
+ATH10K_SPECTRAL=
ATH10K_THERMAL=
ATH10K_TRACING=
ATH10K_DFS_CERTIFIED=

View file

@ -0,0 +1,25 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 17 Jan 2018 11:11:17 +0100
Subject: [PATCH] ath9k: discard undersized packets
Sometimes the hardware will push small packets that trigger a WARN_ON
in mac80211. Discard them early to avoid this issue.
Reported-by: Stijn Tintel <stijn@linux-ipv6.be>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -826,9 +826,9 @@ static int ath9k_rx_skb_preprocess(struc
sc->rx.discard_next = false;
/*
- * Discard zero-length packets.
+ * Discard zero-length packets and packets smaller than an ACK
*/
- if (!rx_stats->rs_datalen) {
+ if (rx_stats->rs_datalen < 10) {
RX_STAT_INC(rx_len_err);
goto corrupt;
}

View file

@ -0,0 +1,39 @@
From 1fd3ae124d5e675f57cf7e3c601fb8f7712e0329 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:38 +0100
Subject: [PATCH] brcmfmac: Fix parameter order in brcmf_sdiod_f0_writeb()
All the other IO functions are the other way round in this
driver. Make this one match.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -230,8 +230,8 @@ void brcmf_sdiod_change_state(struct brc
sdiodev->state = state;
}
-static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func,
- uint regaddr, u8 byte)
+static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte,
+ uint regaddr)
{
int err_ret;
@@ -269,8 +269,8 @@ static int brcmf_sdiod_request_data(stru
if (fn)
sdio_writeb(func, *(u8 *)data, addr, &ret);
else
- ret = brcmf_sdiod_f0_writeb(func, addr,
- *(u8 *)data);
+ ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data,
+ addr);
} else {
if (fn)
*(u8 *)data = sdio_readb(func, addr, &ret);

View file

@ -0,0 +1,105 @@
From 1e6f676f43aa4270ebc5cff8e32a55f72362e042 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:39 +0100
Subject: [PATCH] brcmfmac: Register sizes on hardware are not dependent on
compiler types
The 4 IO functions in this patch are incorrect as they use compiler types
to determine how many bytes to send to the hardware.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -264,7 +264,7 @@ static int brcmf_sdiod_request_data(stru
func = sdiodev->func[fn];
switch (regsz) {
- case sizeof(u8):
+ case 1:
if (write) {
if (fn)
sdio_writeb(func, *(u8 *)data, addr, &ret);
@@ -278,13 +278,13 @@ static int brcmf_sdiod_request_data(stru
*(u8 *)data = sdio_f0_readb(func, addr, &ret);
}
break;
- case sizeof(u16):
+ case 2:
if (write)
sdio_writew(func, *(u16 *)data, addr, &ret);
else
*(u16 *)data = sdio_readw(func, addr, &ret);
break;
- case sizeof(u32):
+ case 4:
if (write)
sdio_writel(func, *(u32 *)data, addr, &ret);
else
@@ -368,7 +368,7 @@ brcmf_sdiod_set_sbaddr_window(struct brc
for (i = 0; i < 3; i++) {
err = brcmf_sdiod_regrw_helper(sdiodev,
SBSDIO_FUNC1_SBADDRLOW + i,
- sizeof(u8), &addr[i], true);
+ 1, &addr[i], true);
if (err) {
brcmf_err("failed at addr: 0x%0x\n",
SBSDIO_FUNC1_SBADDRLOW + i);
@@ -407,7 +407,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d
int retval;
brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
+ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data,
false);
brcmf_dbg(SDIO, "data:0x%02x\n", data);
@@ -423,10 +423,10 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
int retval;
brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
- retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr);
+ retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
if (retval)
goto done;
- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
+ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data,
false);
brcmf_dbg(SDIO, "data:0x%08x\n", data);
@@ -443,7 +443,7 @@ void brcmf_sdiod_regwb(struct brcmf_sdio
int retval;
brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
+ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data,
true);
if (ret)
*ret = retval;
@@ -455,10 +455,10 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
int retval;
brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
- retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr);
+ retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
if (retval)
goto done;
- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
+ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data,
true);
done:
@@ -876,7 +876,7 @@ int brcmf_sdiod_abort(struct brcmf_sdio_
/* issue abort cmd52 command through F0 */
brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT,
- sizeof(t_func), &t_func, true);
+ 1, &t_func, true);
brcmf_dbg(SDIO, "Exit\n");
return 0;

View file

@ -0,0 +1,179 @@
From 0fcc9fe0048422d66bb906eaa73cc75e11ff7345 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:40 +0100
Subject: [PATCH] brcmfmac: Split brcmf_sdiod_regrw_helper() up.
This large function is concealing a LOT of obscure logic about
how the hardware functions. Time to split it up.
This first patch splits the function into two pieces - read and write,
doing away with the rw flag in the process.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 94 +++++++++++++++++-----
1 file changed, 73 insertions(+), 21 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -302,8 +302,8 @@ static int brcmf_sdiod_request_data(stru
return ret;
}
-static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 regsz, void *data, bool write)
+static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr,
+ u8 regsz, void *data)
{
u8 func;
s32 retry = 0;
@@ -324,13 +324,66 @@ static int brcmf_sdiod_regrw_helper(stru
func = SDIO_FUNC_1;
do {
- if (!write)
- memset(data, 0, regsz);
/* for retry wait for 1 ms till bus get settled down */
if (retry)
usleep_range(1000, 2000);
+
+ ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
+ data, true);
+
+ } while (ret != 0 && ret != -ENOMEDIUM &&
+ retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
+
+ if (ret == -ENOMEDIUM) {
+ brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+ } else if (ret != 0) {
+ /*
+ * SleepCSR register access can fail when
+ * waking up the device so reduce this noise
+ * in the logs.
+ */
+ if (addr != SBSDIO_FUNC1_SLEEPCSR)
+ brcmf_err("failed to write data F%d@0x%05x, err: %d\n",
+ func, addr, ret);
+ else
+ brcmf_dbg(SDIO, "failed to write data F%d@0x%05x, err: %d\n",
+ func, addr, ret);
+ }
+
+ return ret;
+}
+
+static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr,
+ u8 regsz, void *data)
+{
+ u8 func;
+ s32 retry = 0;
+ int ret;
+
+ if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
+ return -ENOMEDIUM;
+
+ /*
+ * figure out how to read the register based on address range
+ * 0x00 ~ 0x7FF: function 0 CCCR and FBR
+ * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
+ * The rest: function 1 silicon backplane core registers
+ */
+ if ((addr & ~REG_F0_REG_MASK) == 0)
+ func = SDIO_FUNC_0;
+ else
+ func = SDIO_FUNC_1;
+
+ do {
+ memset(data, 0, regsz);
+
+ /* for retry wait for 1 ms till bus get settled down */
+ if (retry)
+ usleep_range(1000, 2000);
+
ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
- data, write);
+ data, false);
+
} while (ret != 0 && ret != -ENOMEDIUM &&
retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
@@ -343,12 +396,13 @@ static int brcmf_sdiod_regrw_helper(stru
* in the logs.
*/
if (addr != SBSDIO_FUNC1_SLEEPCSR)
- brcmf_err("failed to %s data F%d@0x%05x, err: %d\n",
- write ? "write" : "read", func, addr, ret);
+ brcmf_err("failed to read data F%d@0x%05x, err: %d\n",
+ func, addr, ret);
else
- brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
- write ? "write" : "read", func, addr, ret);
+ brcmf_dbg(SDIO, "failed to read data F%d@0x%05x, err: %d\n",
+ func, addr, ret);
}
+
return ret;
}
@@ -366,13 +420,11 @@ brcmf_sdiod_set_sbaddr_window(struct brc
addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
for (i = 0; i < 3; i++) {
- err = brcmf_sdiod_regrw_helper(sdiodev,
- SBSDIO_FUNC1_SBADDRLOW + i,
- 1, &addr[i], true);
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, addr[i],
+ &err);
if (err) {
brcmf_err("failed at addr: 0x%0x\n",
SBSDIO_FUNC1_SBADDRLOW + i);
- break;
}
}
@@ -407,8 +459,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d
int retval;
brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data,
- false);
+ retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data);
brcmf_dbg(SDIO, "data:0x%02x\n", data);
if (ret)
@@ -426,8 +477,9 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
if (retval)
goto done;
- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data,
- false);
+
+ retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
+
brcmf_dbg(SDIO, "data:0x%08x\n", data);
done:
@@ -443,8 +495,8 @@ void brcmf_sdiod_regwb(struct brcmf_sdio
int retval;
brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data,
- true);
+ retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data);
+
if (ret)
*ret = retval;
}
@@ -458,8 +510,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
if (retval)
goto done;
- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data,
- true);
+
+ retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
done:
if (ret)

View file

@ -0,0 +1,62 @@
From b9b0d290bc0c90a5a262bc89c9d995988ea98669 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:41 +0100
Subject: [PATCH] brcmfmac: Clean up brcmf_sdiod_set_sbaddr_window()
This function sets the address of the IO window used for
SDIO accesses onto the backplane of the chip.
It currently uses 3 separate masks despite the full mask being
defined in the code already. Remove the separate masks and clean up.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 17 +++++------------
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 3 ---
2 files changed, 5 insertions(+), 15 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -410,23 +410,16 @@ static int
brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
{
int err = 0, i;
- u8 addr[3];
+ u32 addr;
if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
return -ENOMEDIUM;
- addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
- addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK;
- addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
+ addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
- for (i = 0; i < 3; i++) {
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, addr[i],
- &err);
- if (err) {
- brcmf_err("failed at addr: 0x%0x\n",
- SBSDIO_FUNC1_SBADDRLOW + i);
- }
- }
+ for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
+ addr & 0xff, &err);
return err;
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -133,9 +133,6 @@
/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
-#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
-#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
-#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
/* Address bits from SBADDR regs */
#define SBSDIO_SBWINDOW_MASK 0xffff8000

View file

@ -0,0 +1,91 @@
From ea243e9077b3545f20d93884e91c50ac0719685a Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:42 +0100
Subject: [PATCH] brcmfmac: Remove dead IO code
The value passed to brcmf_sdiod_addrprep() is *always* 4
remove this parameter and the unused code to handle it.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -425,7 +425,7 @@ brcmf_sdiod_set_sbaddr_window(struct brc
}
static int
-brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr)
+brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
{
uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
@@ -439,9 +439,7 @@ brcmf_sdiod_addrprep(struct brcmf_sdio_d
}
*addr &= SBSDIO_SB_OFT_ADDR_MASK;
-
- if (width == 4)
- *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+ *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
return 0;
}
@@ -467,7 +465,7 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
int retval;
brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
- retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
+ retval = brcmf_sdiod_addrprep(sdiodev, &addr);
if (retval)
goto done;
@@ -500,7 +498,7 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
int retval;
brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
- retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
+ retval = brcmf_sdiod_addrprep(sdiodev, &addr);
if (retval)
goto done;
@@ -736,7 +734,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
+ err = brcmf_sdiod_addrprep(sdiodev, &addr);
if (err)
goto done;
@@ -757,7 +755,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n",
addr, pktq->qlen);
- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
+ err = brcmf_sdiod_addrprep(sdiodev, &addr);
if (err)
goto done;
@@ -801,7 +799,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
memcpy(mypkt->data, buf, nbytes);
- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
+ err = brcmf_sdiod_addrprep(sdiodev, &addr);
if (!err)
err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, addr,
@@ -821,7 +819,7 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen);
- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
+ err = brcmf_sdiod_addrprep(sdiodev, &addr);
if (err)
return err;

View file

@ -0,0 +1,61 @@
From 4a3338ba2a7421db2260159cca5a27bd2ee36d00 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:43 +0100
Subject: [PATCH] brcmfmac: Remove bandaid for SleepCSR
Register access code is not the place for band-aid fixes like this.
If this is a genuine problem, it should be fixed further up in the driver
stack.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 28 +---------------------
1 file changed, 1 insertion(+), 27 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -334,21 +334,8 @@ static int brcmf_sdiod_reg_write(struct
} while (ret != 0 && ret != -ENOMEDIUM &&
retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
- if (ret == -ENOMEDIUM) {
+ if (ret == -ENOMEDIUM)
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
- } else if (ret != 0) {
- /*
- * SleepCSR register access can fail when
- * waking up the device so reduce this noise
- * in the logs.
- */
- if (addr != SBSDIO_FUNC1_SLEEPCSR)
- brcmf_err("failed to write data F%d@0x%05x, err: %d\n",
- func, addr, ret);
- else
- brcmf_dbg(SDIO, "failed to write data F%d@0x%05x, err: %d\n",
- func, addr, ret);
- }
return ret;
}
@@ -389,19 +376,6 @@ static int brcmf_sdiod_reg_read(struct b
if (ret == -ENOMEDIUM)
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
- else if (ret != 0) {
- /*
- * SleepCSR register access can fail when
- * waking up the device so reduce this noise
- * in the logs.
- */
- if (addr != SBSDIO_FUNC1_SLEEPCSR)
- brcmf_err("failed to read data F%d@0x%05x, err: %d\n",
- func, addr, ret);
- else
- brcmf_dbg(SDIO, "failed to read data F%d@0x%05x, err: %d\n",
- func, addr, ret);
- }
return ret;
}

View file

@ -0,0 +1,344 @@
From 993a98a42e6e790fd0d2bf7d55a031513c7ba7dc Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:44 +0100
Subject: [PATCH] brcmfmac: Remove brcmf_sdiod_request_data()
This function is obfuscating how IO works on this chip. Remove it
and push its logic into brcmf_sdiod_reg_{read,write}().
Handling of -ENOMEDIUM is altered, but as that's pretty much broken anyway
we can ignore that.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 237 ++++++++-------------
.../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 2 +-
2 files changed, 87 insertions(+), 152 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -230,6 +230,43 @@ void brcmf_sdiod_change_state(struct brc
sdiodev->state = state;
}
+static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
+ u32 address)
+{
+ int err = 0, i;
+ u32 addr;
+
+ if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
+ return -ENOMEDIUM;
+
+ addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
+
+ for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
+ addr & 0xff, &err);
+
+ return err;
+}
+
+static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
+{
+ uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+ int err = 0;
+
+ if (bar0 != sdiodev->sbwad) {
+ err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
+ if (err)
+ return err;
+
+ sdiodev->sbwad = bar0;
+ }
+
+ *addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ return 0;
+}
+
static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte,
uint regaddr)
{
@@ -249,173 +286,84 @@ static inline int brcmf_sdiod_f0_writeb(
return err_ret;
}
-static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn,
- u32 addr, u8 regsz, void *data, bool write)
-{
- struct sdio_func *func;
- int ret = -EINVAL;
-
- brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
- write, fn, addr, regsz);
-
- /* only allow byte access on F0 */
- if (WARN_ON(regsz > 1 && !fn))
- return -EINVAL;
- func = sdiodev->func[fn];
-
- switch (regsz) {
- case 1:
- if (write) {
- if (fn)
- sdio_writeb(func, *(u8 *)data, addr, &ret);
- else
- ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data,
- addr);
- } else {
- if (fn)
- *(u8 *)data = sdio_readb(func, addr, &ret);
- else
- *(u8 *)data = sdio_f0_readb(func, addr, &ret);
- }
- break;
- case 2:
- if (write)
- sdio_writew(func, *(u16 *)data, addr, &ret);
- else
- *(u16 *)data = sdio_readw(func, addr, &ret);
- break;
- case 4:
- if (write)
- sdio_writel(func, *(u32 *)data, addr, &ret);
- else
- *(u32 *)data = sdio_readl(func, addr, &ret);
- break;
- default:
- brcmf_err("invalid size: %d\n", regsz);
- break;
- }
-
- if (ret)
- brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
- write ? "write" : "read", fn, addr, ret);
-
- return ret;
-}
-
static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr,
u8 regsz, void *data)
{
- u8 func;
- s32 retry = 0;
int ret;
- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
- return -ENOMEDIUM;
-
/*
* figure out how to read the register based on address range
* 0x00 ~ 0x7FF: function 0 CCCR and FBR
* 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
* The rest: function 1 silicon backplane core registers
+ * f0 writes must be bytewise
*/
- if ((addr & ~REG_F0_REG_MASK) == 0)
- func = SDIO_FUNC_0;
- else
- func = SDIO_FUNC_1;
-
- do {
- /* for retry wait for 1 ms till bus get settled down */
- if (retry)
- usleep_range(1000, 2000);
- ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
- data, true);
-
- } while (ret != 0 && ret != -ENOMEDIUM &&
- retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
+ if ((addr & ~REG_F0_REG_MASK) == 0) {
+ if (WARN_ON(regsz > 1))
+ return -EINVAL;
+ ret = brcmf_sdiod_f0_writeb(sdiodev->func[0],
+ *(u8 *)data, addr);
+ } else {
+ switch (regsz) {
+ case 1:
+ sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret);
+ break;
+ case 4:
+ ret = brcmf_sdiod_addrprep(sdiodev, &addr);
+ if (ret)
+ goto done;
- if (ret == -ENOMEDIUM)
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+ sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret);
+ break;
+ default:
+ WARN(1, "Invalid reg size\n");
+ ret = -EINVAL;
+ break;
+ }
+ }
+done:
return ret;
}
static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr,
u8 regsz, void *data)
{
- u8 func;
- s32 retry = 0;
int ret;
- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
- return -ENOMEDIUM;
-
/*
* figure out how to read the register based on address range
* 0x00 ~ 0x7FF: function 0 CCCR and FBR
* 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
* The rest: function 1 silicon backplane core registers
+ * f0 reads must be bytewise
*/
- if ((addr & ~REG_F0_REG_MASK) == 0)
- func = SDIO_FUNC_0;
- else
- func = SDIO_FUNC_1;
-
- do {
- memset(data, 0, regsz);
-
- /* for retry wait for 1 ms till bus get settled down */
- if (retry)
- usleep_range(1000, 2000);
-
- ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
- data, false);
-
- } while (ret != 0 && ret != -ENOMEDIUM &&
- retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
-
- if (ret == -ENOMEDIUM)
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-
- return ret;
-}
-
-static int
-brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
-{
- int err = 0, i;
- u32 addr;
-
- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
- return -ENOMEDIUM;
-
- addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
-
- for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
- addr & 0xff, &err);
-
- return err;
-}
-
-static int
-brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
-{
- uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- int err = 0;
-
- if (bar0 != sdiodev->sbwad) {
- err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
- if (err)
- return err;
+ if ((addr & ~REG_F0_REG_MASK) == 0) {
+ if (WARN_ON(regsz > 1))
+ return -EINVAL;
+ *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret);
+ } else {
+ switch (regsz) {
+ case 1:
+ *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret);
+ break;
+ case 4:
+ ret = brcmf_sdiod_addrprep(sdiodev, &addr);
+ if (ret)
+ goto done;
- sdiodev->sbwad = bar0;
+ *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret);
+ break;
+ default:
+ WARN(1, "Invalid reg size\n");
+ ret = -EINVAL;
+ break;
+ }
}
- *addr &= SBSDIO_SB_OFT_ADDR_MASK;
- *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- return 0;
+done:
+ return ret;
}
u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
@@ -439,15 +387,9 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
int retval;
brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
- retval = brcmf_sdiod_addrprep(sdiodev, &addr);
- if (retval)
- goto done;
-
retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
-
brcmf_dbg(SDIO, "data:0x%08x\n", data);
-done:
if (ret)
*ret = retval;
@@ -472,13 +414,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
int retval;
brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
- retval = brcmf_sdiod_addrprep(sdiodev, &addr);
- if (retval)
- goto done;
-
retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
-done:
if (ret)
*ret = retval;
}
@@ -886,14 +823,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
return bcmerror;
}
-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)
{
- char t_func = (char)fn;
brcmf_dbg(SDIO, "Enter\n");
/* issue abort cmd52 command through F0 */
- brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT,
- 1, &t_func, true);
+ brcmf_sdiod_reg_write(sdiodev, SDIO_CCCR_ABORT, 1, &fn);
brcmf_dbg(SDIO, "Exit\n");
return 0;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -339,7 +339,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
u8 *data, uint size);
/* Issue an abort to the specified function */
-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn);
void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
enum brcmf_sdiod_state state);

View file

@ -0,0 +1,28 @@
From 3508a056a1f45d95c874fc9af8748bf4229432b6 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:45 +0100
Subject: [PATCH] brcmfmac: Fix asymmetric IO functions.
Unlikely to be a problem, but brcmf_sdiod_regrl() is
not symmetric with brcmf_sdiod_regrb() in initializing
the data value on stack. Fix that.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
[arend: reword the commit message a bit]
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -383,7 +383,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d
u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
{
- u32 data = 0;
+ u32 data;
int retval;
brcmf_dbg(SDIO, "addr:0x%08x\n", addr);

View file

@ -0,0 +1,53 @@
From 12e3e74e2820e11d91ee44fd3a190cd80d109faa Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:46 +0100
Subject: [PATCH] brcmfmac: Remove noisy debugging.
If you need debugging this low level, you're doing something wrong.
Remove these noisy debug statements so the code is more readable.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 6 ------
1 file changed, 6 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -371,9 +371,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d
u8 data;
int retval;
- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data);
- brcmf_dbg(SDIO, "data:0x%02x\n", data);
if (ret)
*ret = retval;
@@ -386,9 +384,7 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
u32 data;
int retval;
- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
- brcmf_dbg(SDIO, "data:0x%08x\n", data);
if (ret)
*ret = retval;
@@ -401,7 +397,6 @@ void brcmf_sdiod_regwb(struct brcmf_sdio
{
int retval;
- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data);
if (ret)
@@ -413,7 +408,6 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
{
int retval;
- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
if (ret)

View file

@ -0,0 +1,58 @@
From dd8a2d49e4ed321ab8e7b679499c3a98ccc5ca24 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Mon, 13 Nov 2017 21:35:47 +0100
Subject: [PATCH] brcmfmac: Rename bcmerror to err
Trivial cleanup of nasty variable name
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -746,7 +746,7 @@ int
brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
u8 *data, uint size)
{
- int bcmerror = 0;
+ int err = 0;
struct sk_buff *pkt;
u32 sdaddr;
uint dsize;
@@ -771,8 +771,8 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
/* Do the transfer(s) */
while (size) {
/* Set the backplane window to include the start address */
- bcmerror = brcmf_sdiod_set_sbaddr_window(sdiodev, address);
- if (bcmerror)
+ err = brcmf_sdiod_set_sbaddr_window(sdiodev, address);
+ if (err)
break;
brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
@@ -785,9 +785,9 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
skb_put(pkt, dsize);
if (write)
memcpy(pkt->data, data, dsize);
- bcmerror = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write,
- sdaddr, pkt);
- if (bcmerror) {
+ err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write, sdaddr,
+ pkt);
+ if (err) {
brcmf_err("membytes transfer failed\n");
break;
}
@@ -814,7 +814,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
sdio_release_host(sdiodev->func[1]);
- return bcmerror;
+ return err;
}
int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)

View file

@ -0,0 +1,143 @@
From 8f13c87ccc495e30de5f58bbda967f6edd5bec53 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:26 +0100
Subject: [PATCH] brcmfmac: Split brcmf_sdiod_buffrw function up.
This function needs to be split up into separate read / write variants
for clarity.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 67 +++++++++++++++-------
1 file changed, 45 insertions(+), 22 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -414,8 +414,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
*ret = retval;
}
-static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
- bool write, u32 addr, struct sk_buff *pkt)
+static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev, uint fn,
+ u32 addr, struct sk_buff *pkt)
{
unsigned int req_sz;
int err;
@@ -424,18 +424,36 @@ static int brcmf_sdiod_buffrw(struct brc
req_sz = pkt->len + 3;
req_sz &= (uint)~3;
- if (write)
- err = sdio_memcpy_toio(sdiodev->func[fn], addr,
- ((u8 *)(pkt->data)), req_sz);
- else if (fn == 1)
- err = sdio_memcpy_fromio(sdiodev->func[fn], ((u8 *)(pkt->data)),
- addr, req_sz);
+ if (fn == 1)
+ err = sdio_memcpy_fromio(sdiodev->func[fn],
+ ((u8 *)(pkt->data)), addr, req_sz);
else
/* function 2 read is FIFO operation */
- err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr,
- req_sz);
+ err = sdio_readsb(sdiodev->func[fn],
+ ((u8 *)(pkt->data)), addr, req_sz);
+
+ if (err == -ENOMEDIUM)
+ brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+
+ return err;
+}
+
+static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev, uint fn,
+ u32 addr, struct sk_buff *pkt)
+{
+ unsigned int req_sz;
+ int err;
+
+ /* Single skb use the standard mmc interface */
+ req_sz = pkt->len + 3;
+ req_sz &= (uint)~3;
+
+ err = sdio_memcpy_toio(sdiodev->func[fn], addr,
+ ((u8 *)(pkt->data)), req_sz);
+
if (err == -ENOMEDIUM)
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+
return err;
}
@@ -643,7 +661,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
if (err)
goto done;
- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, pkt);
+ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt);
done:
return err;
@@ -665,14 +683,14 @@ int brcmf_sdiod_recv_chain(struct brcmf_
goto done;
if (pktq->qlen == 1)
- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
- pktq->next);
+ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
+ pktq->next);
else if (!sdiodev->sg_support) {
glom_skb = brcmu_pkt_buf_get_skb(totlen);
if (!glom_skb)
return -ENOMEM;
- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
- glom_skb);
+ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
+ glom_skb);
if (err)
goto done;
@@ -707,8 +725,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
err = brcmf_sdiod_addrprep(sdiodev, &addr);
if (!err)
- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, addr,
- mypkt);
+ err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt);
brcmu_pkt_buf_free_skb(mypkt);
return err;
@@ -730,8 +747,8 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
if (pktq->qlen == 1 || !sdiodev->sg_support)
skb_queue_walk(pktq, skb) {
- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true,
- addr, skb);
+ err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2,
+ addr, skb);
if (err)
break;
}
@@ -783,10 +800,16 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
sdaddr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
skb_put(pkt, dsize);
- if (write)
+
+ if (write) {
memcpy(pkt->data, data, dsize);
- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write, sdaddr,
- pkt);
+ err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_1,
+ sdaddr, pkt);
+ } else {
+ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_1,
+ sdaddr, pkt);
+ }
+
if (err) {
brcmf_err("membytes transfer failed\n");
break;

View file

@ -0,0 +1,34 @@
From 6e24dd012bfda479d0046f7995058f167e1923bc Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:27 +0100
Subject: [PATCH] brcmfmac: whitespace fixes in brcmf_sdiod_send_buf()
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
[arend: mention function in patch subject]
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -714,6 +714,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
int err;
mypkt = brcmu_pkt_buf_get_skb(nbytes);
+
if (!mypkt) {
brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
nbytes);
@@ -728,8 +729,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt);
brcmu_pkt_buf_free_skb(mypkt);
- return err;
+ return err;
}
int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,

View file

@ -0,0 +1,36 @@
From a7323378dcf1f10a98f47b744e6f65e6fd671d84 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:28 +0100
Subject: [PATCH] brcmfmac: Clarify if using braces.
Whilst this if () statement is technically correct, it lacks clarity.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -746,16 +746,17 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
if (err)
return err;
- if (pktq->qlen == 1 || !sdiodev->sg_support)
+ if (pktq->qlen == 1 || !sdiodev->sg_support) {
skb_queue_walk(pktq, skb) {
err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2,
addr, skb);
if (err)
break;
}
- else
+ } else {
err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr,
pktq);
+ }
return err;
}

View file

@ -0,0 +1,831 @@
From 71bd508d7ded8c504ef05d1b4befecfe25e54cb1 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:29 +0100
Subject: [PATCH] brcmfmac: Rename / replace old IO functions with simpler
ones.
Primarily this patch removes:
brcmf_sdiod_f0_writeb()
brcmf_sdiod_reg_write()
brcmf_sdiod_reg_read()
Since we no longer use the quirky method of deciding which function to
address via the address being accessed, take the opportunity to rename
some IO functions more in line with common kernel code. We also convert
those that map directly to sdio_{read,write}*() to macros.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 169 +++----------------
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 186 ++++++++++-----------
.../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 28 +++-
3 files changed, 138 insertions(+), 245 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -137,27 +137,27 @@ int brcmf_sdiod_intr_register(struct brc
if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) {
/* assign GPIO to SDIO core */
addr = CORE_CC_REG(SI_ENUM_BASE, gpiocontrol);
- gpiocontrol = brcmf_sdiod_regrl(sdiodev, addr, &ret);
+ gpiocontrol = brcmf_sdiod_readl(sdiodev, addr, &ret);
gpiocontrol |= 0x2;
- brcmf_sdiod_regwl(sdiodev, addr, gpiocontrol, &ret);
+ brcmf_sdiod_writel(sdiodev, addr, gpiocontrol, &ret);
- brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_SELECT, 0xf,
- &ret);
- brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret);
- brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_SELECT,
+ 0xf, &ret);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret);
}
/* must configure SDIO_CCCR_IENx to enable irq */
- data = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
+ data = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_IENx, &ret);
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret);
/* redirect, configure and enable io for interrupt signal */
data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
data |= SDIO_SEPINT_ACT_HI;
- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
-
+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT,
+ data, &ret);
sdio_release_host(sdiodev->func[1]);
} else {
brcmf_dbg(SDIO, "Entering\n");
@@ -183,8 +183,8 @@ void brcmf_sdiod_intr_unregister(struct
pdata = &sdiodev->settings->bus.sdio;
sdio_claim_host(sdiodev->func[1]);
- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
sdio_release_host(sdiodev->func[1]);
sdiodev->oob_irq_requested = false;
@@ -242,8 +242,8 @@ static int brcmf_sdiod_set_sbaddr_window
addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
- addr & 0xff, &err);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
+ addr & 0xff, &err);
return err;
}
@@ -267,124 +267,15 @@ static int brcmf_sdiod_addrprep(struct b
return 0;
}
-static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte,
- uint regaddr)
-{
- int err_ret;
-
- /*
- * Can only directly write to some F0 registers.
- * Handle CCCR_IENx and CCCR_ABORT command
- * as a special case.
- */
- if ((regaddr == SDIO_CCCR_ABORT) ||
- (regaddr == SDIO_CCCR_IENx))
- sdio_writeb(func, byte, regaddr, &err_ret);
- else
- sdio_f0_writeb(func, byte, regaddr, &err_ret);
-
- return err_ret;
-}
-
-static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 regsz, void *data)
-{
- int ret;
-
- /*
- * figure out how to read the register based on address range
- * 0x00 ~ 0x7FF: function 0 CCCR and FBR
- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
- * The rest: function 1 silicon backplane core registers
- * f0 writes must be bytewise
- */
-
- if ((addr & ~REG_F0_REG_MASK) == 0) {
- if (WARN_ON(regsz > 1))
- return -EINVAL;
- ret = brcmf_sdiod_f0_writeb(sdiodev->func[0],
- *(u8 *)data, addr);
- } else {
- switch (regsz) {
- case 1:
- sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret);
- break;
- case 4:
- ret = brcmf_sdiod_addrprep(sdiodev, &addr);
- if (ret)
- goto done;
-
- sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret);
- break;
- default:
- WARN(1, "Invalid reg size\n");
- ret = -EINVAL;
- break;
- }
- }
-
-done:
- return ret;
-}
-
-static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 regsz, void *data)
-{
- int ret;
-
- /*
- * figure out how to read the register based on address range
- * 0x00 ~ 0x7FF: function 0 CCCR and FBR
- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
- * The rest: function 1 silicon backplane core registers
- * f0 reads must be bytewise
- */
- if ((addr & ~REG_F0_REG_MASK) == 0) {
- if (WARN_ON(regsz > 1))
- return -EINVAL;
- *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret);
- } else {
- switch (regsz) {
- case 1:
- *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret);
- break;
- case 4:
- ret = brcmf_sdiod_addrprep(sdiodev, &addr);
- if (ret)
- goto done;
-
- *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret);
- break;
- default:
- WARN(1, "Invalid reg size\n");
- ret = -EINVAL;
- break;
- }
- }
-
-done:
- return ret;
-}
-
-u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
+u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
{
- u8 data;
+ u32 data = 0;
int retval;
- retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data);
-
- if (ret)
- *ret = retval;
-
- return data;
-}
+ retval = brcmf_sdiod_addrprep(sdiodev, &addr);
-u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
-{
- u32 data;
- int retval;
-
- retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
+ if (!retval)
+ data = sdio_readl(sdiodev->func[1], addr, &retval);
if (ret)
*ret = retval;
@@ -392,23 +283,15 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
return data;
}
-void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 data, int *ret)
+void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr,
+ u32 data, int *ret)
{
int retval;
- retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data);
-
- if (ret)
- *ret = retval;
-}
-
-void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u32 data, int *ret)
-{
- int retval;
+ retval = brcmf_sdiod_addrprep(sdiodev, &addr);
- retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
+ if (!retval)
+ sdio_writel(sdiodev->func[1], data, addr, &retval);
if (ret)
*ret = retval;
@@ -846,8 +729,8 @@ int brcmf_sdiod_abort(struct brcmf_sdio_
{
brcmf_dbg(SDIO, "Enter\n");
- /* issue abort cmd52 command through F0 */
- brcmf_sdiod_reg_write(sdiodev, SDIO_CCCR_ABORT, 1, &fn);
+ /* Issue abort cmd52 command through F0 */
+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, fn, NULL);
brcmf_dbg(SDIO, "Exit\n");
return 0;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -669,7 +669,7 @@ static int r_sdreg32(struct brcmf_sdio *
int ret;
core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- *regvar = brcmf_sdiod_regrl(bus->sdiodev, core->base + offset, &ret);
+ *regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret);
return ret;
}
@@ -680,7 +680,7 @@ static int w_sdreg32(struct brcmf_sdio *
int ret;
core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- brcmf_sdiod_regwl(bus->sdiodev, core->base + reg_offset, regval, &ret);
+ brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret);
return ret;
}
@@ -697,8 +697,7 @@ brcmf_sdio_kso_control(struct brcmf_sdio
wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
/* 1st KSO write goes to AOS wake up core if device is asleep */
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
- wr_val, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
if (on) {
/* device WAKEUP through KSO:
@@ -724,7 +723,7 @@ brcmf_sdio_kso_control(struct brcmf_sdio
* just one write attempt may fail,
* read it back until it matches written value
*/
- rd_val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ rd_val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
&err);
if (!err) {
if ((rd_val & bmask) == cmp_val)
@@ -734,9 +733,11 @@ brcmf_sdio_kso_control(struct brcmf_sdio
/* bail out upon subsequent access errors */
if (err && (err_cnt++ > BRCMF_SDIO_MAX_ACCESS_ERRORS))
break;
+
udelay(KSO_WAIT_US);
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
- wr_val, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val,
+ &err);
+
} while (try_cnt++ < MAX_KSO_ATTEMPTS);
if (try_cnt > 2)
@@ -772,15 +773,15 @@ static int brcmf_sdio_htclk(struct brcmf
clkreq =
bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- clkreq, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ clkreq, &err);
if (err) {
brcmf_err("HT Avail request error: %d\n", err);
return -EBADE;
}
/* Check current status */
- clkctl = brcmf_sdiod_regrb(bus->sdiodev,
+ clkctl = brcmf_sdiod_readb(bus->sdiodev,
SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (err) {
brcmf_err("HT Avail read error: %d\n", err);
@@ -790,35 +791,34 @@ static int brcmf_sdio_htclk(struct brcmf
/* Go to pending and await interrupt if appropriate */
if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
/* Allow only clock-available interrupt */
- devctl = brcmf_sdiod_regrb(bus->sdiodev,
+ devctl = brcmf_sdiod_readb(bus->sdiodev,
SBSDIO_DEVICE_CTL, &err);
if (err) {
- brcmf_err("Devctl error setting CA: %d\n",
- err);
+ brcmf_err("Devctl error setting CA: %d\n", err);
return -EBADE;
}
devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
- devctl, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+ devctl, &err);
brcmf_dbg(SDIO, "CLKCTL: set PENDING\n");
bus->clkstate = CLK_PENDING;
return 0;
} else if (bus->clkstate == CLK_PENDING) {
/* Cancel CA-only interrupt filter */
- devctl = brcmf_sdiod_regrb(bus->sdiodev,
+ devctl = brcmf_sdiod_readb(bus->sdiodev,
SBSDIO_DEVICE_CTL, &err);
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
- devctl, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+ devctl, &err);
}
/* Otherwise, wait here (polling) for HT Avail */
timeout = jiffies +
msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000);
while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
- clkctl = brcmf_sdiod_regrb(bus->sdiodev,
+ clkctl = brcmf_sdiod_readb(bus->sdiodev,
SBSDIO_FUNC1_CHIPCLKCSR,
&err);
if (time_after(jiffies, timeout))
@@ -852,16 +852,16 @@ static int brcmf_sdio_htclk(struct brcmf
if (bus->clkstate == CLK_PENDING) {
/* Cancel CA-only interrupt filter */
- devctl = brcmf_sdiod_regrb(bus->sdiodev,
+ devctl = brcmf_sdiod_readb(bus->sdiodev,
SBSDIO_DEVICE_CTL, &err);
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
- devctl, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+ devctl, &err);
}
bus->clkstate = CLK_SDONLY;
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- clkreq, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ clkreq, &err);
brcmf_dbg(SDIO, "CLKCTL: turned OFF\n");
if (err) {
brcmf_err("Failed access turning clock off: %d\n",
@@ -951,14 +951,14 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *
/* Going to sleep */
if (sleep) {
- clkcsr = brcmf_sdiod_regrb(bus->sdiodev,
+ clkcsr = brcmf_sdiod_readb(bus->sdiodev,
SBSDIO_FUNC1_CHIPCLKCSR,
&err);
if ((clkcsr & SBSDIO_CSR_MASK) == 0) {
brcmf_dbg(SDIO, "no clock, set ALP\n");
- brcmf_sdiod_regwb(bus->sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR,
- SBSDIO_ALP_AVAIL_REQ, &err);
+ brcmf_sdiod_writeb(bus->sdiodev,
+ SBSDIO_FUNC1_CHIPCLKCSR,
+ SBSDIO_ALP_AVAIL_REQ, &err);
}
err = brcmf_sdio_kso_control(bus, false);
} else {
@@ -1178,16 +1178,16 @@ static void brcmf_sdio_rxfail(struct brc
if (abort)
brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
- SFC_RF_TERM, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
+ &err);
bus->sdcnt.f1regdata++;
/* Wait until the packet has been flushed (device/FIFO stable) */
for (lastrbc = retries = 0xffff; retries > 0; retries--) {
- hi = brcmf_sdiod_regrb(bus->sdiodev,
- SBSDIO_FUNC1_RFRAMEBCHI, &err);
- lo = brcmf_sdiod_regrb(bus->sdiodev,
- SBSDIO_FUNC1_RFRAMEBCLO, &err);
+ hi = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_RFRAMEBCHI,
+ &err);
+ lo = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_RFRAMEBCLO,
+ &err);
bus->sdcnt.f1regdata += 2;
if ((hi == 0) && (lo == 0))
@@ -1229,12 +1229,12 @@ static void brcmf_sdio_txfail(struct brc
bus->sdcnt.tx_sderrs++;
brcmf_sdiod_abort(sdiodev, SDIO_FUNC_2);
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
bus->sdcnt.f1regdata++;
for (i = 0; i < 3; i++) {
- hi = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_WFRAMEBCHI, NULL);
- lo = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL);
+ hi = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_WFRAMEBCHI, NULL);
+ lo = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL);
bus->sdcnt.f1regdata += 2;
if ((hi == 0) && (lo == 0))
break;
@@ -2446,11 +2446,11 @@ static void brcmf_sdio_bus_stop(struct d
bus->hostintmask = 0;
/* Force backplane clocks to assure F2 interrupt propagates */
- saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
&err);
if (!err)
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
if (err)
brcmf_err("Failed to force clock for F2: err %d\n",
err);
@@ -2509,7 +2509,7 @@ static int brcmf_sdio_intr_rstatus(struc
buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
addr = buscore->base + offsetof(struct sdpcmd_regs, intstatus);
- val = brcmf_sdiod_regrl(bus->sdiodev, addr, &ret);
+ val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
bus->sdcnt.f1regdata++;
if (ret != 0)
return ret;
@@ -2519,7 +2519,7 @@ static int brcmf_sdio_intr_rstatus(struc
/* Clear interrupts */
if (val) {
- brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret);
+ brcmf_sdiod_writel(bus->sdiodev, addr, val, &ret);
bus->sdcnt.f1regdata++;
atomic_or(val, &bus->intstatus);
}
@@ -2545,23 +2545,23 @@ static void brcmf_sdio_dpc(struct brcmf_
#ifdef DEBUG
/* Check for inconsistent device control */
- devctl = brcmf_sdiod_regrb(bus->sdiodev,
- SBSDIO_DEVICE_CTL, &err);
+ devctl = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+ &err);
#endif /* DEBUG */
/* Read CSR, if clock on switch to AVAIL, else ignore */
- clkctl = brcmf_sdiod_regrb(bus->sdiodev,
+ clkctl = brcmf_sdiod_readb(bus->sdiodev,
SBSDIO_FUNC1_CHIPCLKCSR, &err);
brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
devctl, clkctl);
if (SBSDIO_HTAV(clkctl)) {
- devctl = brcmf_sdiod_regrb(bus->sdiodev,
+ devctl = brcmf_sdiod_readb(bus->sdiodev,
SBSDIO_DEVICE_CTL, &err);
devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
- devctl, &err);
+ brcmf_sdiod_writeb(bus->sdiodev,
+ SBSDIO_DEVICE_CTL, devctl, &err);
bus->clkstate = CLK_AVAIL;
}
}
@@ -3347,31 +3347,31 @@ static void brcmf_sdio_sr_init(struct br
brcmf_dbg(TRACE, "Enter\n");
- val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err);
+ val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err);
if (err) {
brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
return;
}
val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err);
if (err) {
brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
return;
}
/* Add CMD14 Support */
- brcmf_sdiod_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
- (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
- SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
- &err);
+ brcmf_sdiod_func0_wb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
+ (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
+ SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
+ &err);
if (err) {
brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
return;
}
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- SBSDIO_FORCE_HT, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ SBSDIO_FORCE_HT, &err);
if (err) {
brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
return;
@@ -3394,7 +3394,7 @@ static int brcmf_sdio_kso_init(struct br
if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12)
return 0;
- val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
+ val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
if (err) {
brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n");
return err;
@@ -3403,8 +3403,8 @@ static int brcmf_sdio_kso_init(struct br
if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN <<
SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
- val, &err);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ val, &err);
if (err) {
brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n");
return err;
@@ -3565,9 +3565,9 @@ static void brcmf_sdio_bus_watchdog(stru
u8 devpend;
sdio_claim_host(bus->sdiodev->func[1]);
- devpend = brcmf_sdiod_regrb(bus->sdiodev,
- SDIO_CCCR_INTx,
- NULL);
+ devpend = brcmf_sdiod_func0_rb(bus->sdiodev,
+ SDIO_CCCR_INTx,
+ NULL);
sdio_release_host(bus->sdiodev->func[1]);
intstatus = devpend & (INTR_STATUS_FUNC1 |
INTR_STATUS_FUNC2);
@@ -3705,12 +3705,12 @@ brcmf_sdio_drivestrengthinit(struct brcm
}
}
addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
- brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
- cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
+ brcmf_sdiod_writel(sdiodev, addr, 1, NULL);
+ cc_data_temp = brcmf_sdiod_readl(sdiodev, addr, NULL);
cc_data_temp &= ~str_mask;
drivestrength_sel <<= str_shift;
cc_data_temp |= drivestrength_sel;
- brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL);
+ brcmf_sdiod_writel(sdiodev, addr, cc_data_temp, NULL);
brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
str_tab[i].strength, drivestrength, cc_data_temp);
@@ -3725,7 +3725,7 @@ static int brcmf_sdio_buscoreprep(void *
/* Try forcing SDIO core to do ALPAvail request only */
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
if (err) {
brcmf_err("error writing for HT off\n");
return err;
@@ -3733,8 +3733,7 @@ static int brcmf_sdio_buscoreprep(void *
/* If register supported, wait for ALPAvail and then force ALP */
/* This may take up to 15 milliseconds */
- clkval = brcmf_sdiod_regrb(sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR, NULL);
+ clkval = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
if ((clkval & ~SBSDIO_AVBITS) != clkset) {
brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
@@ -3742,10 +3741,11 @@ static int brcmf_sdio_buscoreprep(void *
return -EACCES;
}
- SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
- !SBSDIO_ALPAV(clkval)),
- PMU_MAX_TRANSITION_DLY);
+ SPINWAIT(((clkval = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ NULL)),
+ !SBSDIO_ALPAV(clkval)),
+ PMU_MAX_TRANSITION_DLY);
+
if (!SBSDIO_ALPAV(clkval)) {
brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
clkval);
@@ -3753,11 +3753,11 @@ static int brcmf_sdio_buscoreprep(void *
}
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
udelay(65);
/* Also, disable the extra SDIO pull-ups */
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
return 0;
}
@@ -3772,7 +3772,7 @@ static void brcmf_sdio_buscore_activate(
/* clear all interrupts */
core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV);
reg_addr = core->base + offsetof(struct sdpcmd_regs, intstatus);
- brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
+ brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
if (rstvec)
/* Write reset vector to address 0 */
@@ -3785,7 +3785,7 @@ static u32 brcmf_sdio_buscore_read32(voi
struct brcmf_sdio_dev *sdiodev = ctx;
u32 val, rev;
- val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
+ val = brcmf_sdiod_readl(sdiodev, addr, NULL);
if ((sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
@@ -3802,7 +3802,7 @@ static void brcmf_sdio_buscore_write32(v
{
struct brcmf_sdio_dev *sdiodev = ctx;
- brcmf_sdiod_regwl(sdiodev, addr, val, NULL);
+ brcmf_sdiod_writel(sdiodev, addr, val, NULL);
}
static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
@@ -3826,18 +3826,18 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
sdio_claim_host(sdiodev->func[1]);
pr_debug("F1 signature read @0x18000000=0x%4x\n",
- brcmf_sdiod_regrl(sdiodev, SI_ENUM_BASE, NULL));
+ brcmf_sdiod_readl(sdiodev, SI_ENUM_BASE, NULL));
/*
* Force PLL off until brcmf_chip_attach()
* programs PLL control regs
*/
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- BRCMF_INIT_CLKCTL1, &err);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, BRCMF_INIT_CLKCTL1,
+ &err);
if (!err)
- clkctl = brcmf_sdiod_regrb(sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ clkctl = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ &err);
if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
brcmf_err("ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
@@ -3897,25 +3897,25 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength);
/* Set card control so an SDIO card reset does a WLAN backplane reset */
- reg_val = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err);
+ reg_val = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err);
if (err)
goto fail;
reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
if (err)
goto fail;
/* set PMUControl so a backplane reset does PMU state reload */
reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol);
- reg_val = brcmf_sdiod_regrl(sdiodev, reg_addr, &err);
+ reg_val = brcmf_sdiod_readl(sdiodev, reg_addr, &err);
if (err)
goto fail;
reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
- brcmf_sdiod_regwl(sdiodev, reg_addr, reg_val, &err);
+ brcmf_sdiod_writel(sdiodev, reg_addr, reg_val, &err);
if (err)
goto fail;
@@ -4055,10 +4055,10 @@ static void brcmf_sdio_firmware_callback
goto release;
/* Force clocks on backplane to be sure F2 interrupt propagates */
- saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (!err) {
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
}
if (err) {
brcmf_err("Failed to force clock for F2: err %d\n", err);
@@ -4080,7 +4080,7 @@ static void brcmf_sdio_firmware_callback
w_sdreg32(bus, bus->hostintmask,
offsetof(struct sdpcmd_regs, hostintmask));
- brcmf_sdiod_regwb(sdiodev, SBSDIO_WATERMARK, 8, &err);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
} else {
/* Disable F2 again */
sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
@@ -4091,8 +4091,8 @@ static void brcmf_sdio_firmware_callback
brcmf_sdio_sr_init(bus);
} else {
/* Restore previous clock setting */
- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- saveclk, &err);
+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ saveclk, &err);
}
if (err == 0) {
@@ -4225,7 +4225,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
bus->rxflow = false;
/* Done with backplane-dependent accesses, can drop clock... */
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
sdio_release_host(bus->sdiodev->func[1]);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -50,6 +50,7 @@
#define SBSDIO_NUM_FUNCTION 3
/* function 0 vendor specific CCCR registers */
+
#define SDIO_CCCR_BRCM_CARDCAP 0xf0
#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
@@ -131,8 +132,6 @@
/* with b15, maps to 32-bit SB access */
#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000
-/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
-
/* Address bits from SBADDR regs */
#define SBSDIO_SBWINDOW_MASK 0xffff8000
@@ -293,13 +292,24 @@ struct sdpcmd_regs {
int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev);
void brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev);
-/* sdio device register access interface */
-u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
-u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
-void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data,
- int *ret);
-void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
- int *ret);
+/* SDIO device register access interface */
+/* Accessors for SDIO Function 0 */
+#define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
+ sdio_readb((sdiodev)->func[0], (addr), (r))
+
+#define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
+ sdio_writeb((sdiodev)->func[0], (v), (addr), (ret))
+
+/* Accessors for SDIO Function 1 */
+#define brcmf_sdiod_readb(sdiodev, addr, r) \
+ sdio_readb((sdiodev)->func[1], (addr), (r))
+
+#define brcmf_sdiod_writeb(sdiodev, addr, v, ret) \
+ sdio_writeb((sdiodev)->func[1], (v), (addr), (ret))
+
+u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
+void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
+ int *ret);
/* Buffer transfer to/from device (client) core via cmd53.
* fn: function number

View file

@ -0,0 +1,59 @@
From eeef8a5da781e11746347b3cd9f1942be48ebaf0 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:30 +0100
Subject: [PATCH] brcmfmac: Tidy register definitions a little
Trivial tidy of register definitions.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 4 ++--
.../net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 19 ++++++++++---------
2 files changed, 12 insertions(+), 11 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -153,9 +153,9 @@ int brcmf_sdiod_intr_register(struct brc
brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret);
/* redirect, configure and enable io for interrupt signal */
- data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
+ data = SDIO_CCCR_BRCM_SEPINT_MASK | SDIO_CCCR_BRCM_SEPINT_OE;
if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
- data |= SDIO_SEPINT_ACT_HI;
+ data |= SDIO_CCCR_BRCM_SEPINT_ACT_HI;
brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT,
data, &ret);
sdio_release_host(sdiodev->func[1]);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -52,16 +52,17 @@
/* function 0 vendor specific CCCR registers */
#define SDIO_CCCR_BRCM_CARDCAP 0xf0
-#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
-#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
-#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
-#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
-#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02
-#define SDIO_CCCR_BRCM_SEPINT 0xf2
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT BIT(1)
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT BIT(2)
+#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC BIT(3)
+
+#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
+#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET BIT(1)
-#define SDIO_SEPINT_MASK 0x01
-#define SDIO_SEPINT_OE 0x02
-#define SDIO_SEPINT_ACT_HI 0x04
+#define SDIO_CCCR_BRCM_SEPINT 0xf2
+#define SDIO_CCCR_BRCM_SEPINT_MASK BIT(0)
+#define SDIO_CCCR_BRCM_SEPINT_OE BIT(1)
+#define SDIO_CCCR_BRCM_SEPINT_ACT_HI BIT(2)
/* function 1 miscellaneous registers */

View file

@ -0,0 +1,190 @@
From a7c3aa1509e243a09c5b1660c8702d792ca76aed Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:31 +0100
Subject: [PATCH] brcmfmac: Remove brcmf_sdiod_addrprep()
This function has become trivial enough that it may as well be pushed into
its callers, which has the side-benefit of clarifying what's going on.
Remove it, and rename brcmf_sdiod_set_sbaddr_window() to
brcmf_sdiod_set_backplane_window() as it's easier to understand.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 84 ++++++++++++----------
1 file changed, 46 insertions(+), 38 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -230,41 +230,25 @@ void brcmf_sdiod_change_state(struct brc
sdiodev->state = state;
}
-static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
- u32 address)
+static int brcmf_sdiod_set_backplane_window(struct brcmf_sdio_dev *sdiodev,
+ u32 addr)
{
+ u32 v, bar0 = addr & SBSDIO_SBWINDOW_MASK;
int err = 0, i;
- u32 addr;
- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
- return -ENOMEDIUM;
+ if (bar0 == sdiodev->sbwad)
+ return 0;
- addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
+ v = bar0 >> 8;
- for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
+ for (i = 0 ; i < 3 && !err ; i++, v >>= 8)
brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
- addr & 0xff, &err);
-
- return err;
-}
-
-static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
-{
- uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- int err = 0;
-
- if (bar0 != sdiodev->sbwad) {
- err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
- if (err)
- return err;
+ v & 0xff, &err);
+ if (!err)
sdiodev->sbwad = bar0;
- }
- *addr &= SBSDIO_SB_OFT_ADDR_MASK;
- *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- return 0;
+ return err;
}
u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
@@ -272,11 +256,16 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_
u32 data = 0;
int retval;
- retval = brcmf_sdiod_addrprep(sdiodev, &addr);
+ retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+ if (retval)
+ goto out;
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- if (!retval)
- data = sdio_readl(sdiodev->func[1], addr, &retval);
+ data = sdio_readl(sdiodev->func[1], addr, &retval);
+out:
if (ret)
*ret = retval;
@@ -288,11 +277,16 @@ void brcmf_sdiod_writel(struct brcmf_sdi
{
int retval;
- retval = brcmf_sdiod_addrprep(sdiodev, &addr);
+ retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+ if (retval)
+ goto out;
- if (!retval)
- sdio_writel(sdiodev->func[1], data, addr, &retval);
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+ sdio_writel(sdiodev->func[1], data, addr, &retval);
+
+out:
if (ret)
*ret = retval;
}
@@ -540,10 +534,13 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
- err = brcmf_sdiod_addrprep(sdiodev, &addr);
+ err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
if (err)
goto done;
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt);
done:
@@ -561,10 +558,13 @@ int brcmf_sdiod_recv_chain(struct brcmf_
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n",
addr, pktq->qlen);
- err = brcmf_sdiod_addrprep(sdiodev, &addr);
+ err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
if (err)
goto done;
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
if (pktq->qlen == 1)
err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
pktq->next);
@@ -606,7 +606,12 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
memcpy(mypkt->data, buf, nbytes);
- err = brcmf_sdiod_addrprep(sdiodev, &addr);
+ err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+ if (err)
+ return err;
+
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
if (!err)
err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt);
@@ -625,10 +630,13 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen);
- err = brcmf_sdiod_addrprep(sdiodev, &addr);
+ err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
if (err)
return err;
+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
if (pktq->qlen == 1 || !sdiodev->sg_support) {
skb_queue_walk(pktq, skb) {
err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2,
@@ -673,7 +681,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
/* Do the transfer(s) */
while (size) {
/* Set the backplane window to include the start address */
- err = brcmf_sdiod_set_sbaddr_window(sdiodev, address);
+ err = brcmf_sdiod_set_backplane_window(sdiodev, address);
if (err)
break;
@@ -716,7 +724,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
dev_kfree_skb(pkt);
/* Return the window to backplane enumeration space for core access */
- if (brcmf_sdiod_set_sbaddr_window(sdiodev, sdiodev->sbwad))
+ if (brcmf_sdiod_set_backplane_window(sdiodev, sdiodev->sbwad))
brcmf_err("FAILED to set window back to 0x%x\n",
sdiodev->sbwad);

View file

@ -0,0 +1,32 @@
From c900072bd6faff089aa4fb7b19136a2a0fe3baf0 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:32 +0100
Subject: [PATCH] brcmfmac: remove unnecessary call to
brcmf_sdiod_set_backplane_window()
All functions that might require the window address changing call
brcmf_sdiod_set_backplane_window() prior to access. Thus resetting
the window is not required.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
[arend: corrected the driver prefix in the subject]
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 -----
1 file changed, 5 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -723,11 +723,6 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
dev_kfree_skb(pkt);
- /* Return the window to backplane enumeration space for core access */
- if (brcmf_sdiod_set_backplane_window(sdiodev, sdiodev->sbwad))
- brcmf_err("FAILED to set window back to 0x%x\n",
- sdiodev->sbwad);
-
sdio_release_host(sdiodev->func[1]);
return err;

View file

@ -0,0 +1,134 @@
From e4c05fc3c0a6c79376f72f17d08014477e962ada Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:33 +0100
Subject: [PATCH] brcmfmac: Cleanup offsetof()
Create a macro to make the code a bit more readable, whilst we're stuck
with using struct element offsets as register offsets.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
[arend: rename macro to SD_REG]
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 35 +++++++++-------------
1 file changed, 14 insertions(+), 21 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -161,6 +161,8 @@ struct rte_console {
#define CORE_BUS_REG(base, field) \
(base + offsetof(struct sdpcmd_regs, field))
+#define SD_REG(field) \
+ (offsetof(struct sdpcmd_regs, field))
/* SDIO function 1 register CHIPCLKCSR */
/* Force ALP request to backplane */
@@ -1087,12 +1089,10 @@ static u32 brcmf_sdio_hostmail(struct br
brcmf_dbg(SDIO, "Enter\n");
/* Read mailbox data and ack that we did so */
- ret = r_sdreg32(bus, &hmb_data,
- offsetof(struct sdpcmd_regs, tohostmailboxdata));
+ ret = r_sdreg32(bus, &hmb_data, SD_REG(tohostmailboxdata));
if (ret == 0)
- w_sdreg32(bus, SMB_INT_ACK,
- offsetof(struct sdpcmd_regs, tosbmailbox));
+ w_sdreg32(bus, SMB_INT_ACK, SD_REG(tosbmailbox));
bus->sdcnt.f1regdata += 2;
/* dongle indicates the firmware has halted/crashed */
@@ -1207,8 +1207,7 @@ static void brcmf_sdio_rxfail(struct brc
if (rtx) {
bus->sdcnt.rxrtx++;
- err = w_sdreg32(bus, SMB_NAK,
- offsetof(struct sdpcmd_regs, tosbmailbox));
+ err = w_sdreg32(bus, SMB_NAK, SD_REG(tosbmailbox));
bus->sdcnt.f1regdata++;
if (err == 0)
@@ -2333,9 +2332,7 @@ static uint brcmf_sdio_sendfromq(struct
if (!bus->intr) {
/* Check device status, signal pending interrupt */
sdio_claim_host(bus->sdiodev->func[1]);
- ret = r_sdreg32(bus, &intstatus,
- offsetof(struct sdpcmd_regs,
- intstatus));
+ ret = r_sdreg32(bus, &intstatus, SD_REG(intstatus));
sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2txdata++;
if (ret != 0)
@@ -2441,7 +2438,7 @@ static void brcmf_sdio_bus_stop(struct d
brcmf_sdio_bus_sleep(bus, false, false);
/* Disable and clear interrupts at the chip level also */
- w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
+ w_sdreg32(bus, 0, SD_REG(hostintmask));
local_hostintmask = bus->hostintmask;
bus->hostintmask = 0;
@@ -2460,8 +2457,7 @@ static void brcmf_sdio_bus_stop(struct d
sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
/* Clear any pending interrupts now that F2 is disabled */
- w_sdreg32(bus, local_hostintmask,
- offsetof(struct sdpcmd_regs, intstatus));
+ w_sdreg32(bus, local_hostintmask, SD_REG(intstatus));
sdio_release_host(sdiodev->func[1]);
}
@@ -2507,7 +2503,7 @@ static int brcmf_sdio_intr_rstatus(struc
int ret;
buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- addr = buscore->base + offsetof(struct sdpcmd_regs, intstatus);
+ addr = buscore->base + SD_REG(intstatus);
val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
bus->sdcnt.f1regdata++;
@@ -2584,11 +2580,9 @@ static void brcmf_sdio_dpc(struct brcmf_
*/
if (intstatus & I_HMB_FC_CHANGE) {
intstatus &= ~I_HMB_FC_CHANGE;
- err = w_sdreg32(bus, I_HMB_FC_CHANGE,
- offsetof(struct sdpcmd_regs, intstatus));
+ err = w_sdreg32(bus, I_HMB_FC_CHANGE, SD_REG(intstatus));
- err = r_sdreg32(bus, &newstatus,
- offsetof(struct sdpcmd_regs, intstatus));
+ err = r_sdreg32(bus, &newstatus, SD_REG(intstatus));
bus->sdcnt.f1regdata += 2;
atomic_set(&bus->fcstate,
!!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)));
@@ -3771,7 +3765,7 @@ static void brcmf_sdio_buscore_activate(
/* clear all interrupts */
core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV);
- reg_addr = core->base + offsetof(struct sdpcmd_regs, intstatus);
+ reg_addr = core->base + SD_REG(intstatus);
brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
if (rstvec)
@@ -4067,7 +4061,7 @@ static void brcmf_sdio_firmware_callback
/* Enable function 2 (frame transfers) */
w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
- offsetof(struct sdpcmd_regs, tosbmailboxdata));
+ SD_REG(tosbmailboxdata));
err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
@@ -4077,8 +4071,7 @@ static void brcmf_sdio_firmware_callback
if (!err) {
/* Set up the interrupt mask and enable interrupts */
bus->hostintmask = HOSTINTMASK;
- w_sdreg32(bus, bus->hostintmask,
- offsetof(struct sdpcmd_regs, hostintmask));
+ w_sdreg32(bus, bus->hostintmask, SD_REG(hostintmask));
brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
} else {

View file

@ -0,0 +1,26 @@
From 5cfe38f1f8d3c6b98e15b8cfde05028a3c79930b Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:34 +0100
Subject: [PATCH] brcmfmac: Remove unused macro.
This macro is used exactly nowhere in the code. Delete it.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 --
1 file changed, 2 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -159,8 +159,6 @@ struct rte_console {
/* manfid tuple length, include tuple, link bytes */
#define SBSDIO_CIS_MANFID_TUPLE_LEN 6
-#define CORE_BUS_REG(base, field) \
- (base + offsetof(struct sdpcmd_regs, field))
#define SD_REG(field) \
(offsetof(struct sdpcmd_regs, field))

View file

@ -0,0 +1,128 @@
From 21a10846d09db3c5e3bdfb0be0fc7aa9fdc7000a Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Fri, 8 Dec 2017 13:10:35 +0100
Subject: [PATCH] brcmfmac: Remove repeated calls to brcmf_chip_get_core()
There is no need to repeatdly call brcmf_chip_get_core(), which
traverses a list of cores every time its called (including during
register access code!).
Call it once, and store a pointer to the core structure. The existing
code does nto keep track of users of the cores anyway, and even so, this
will allow for easier refcounting in future.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 25 +++++++++++++---------
1 file changed, 15 insertions(+), 10 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -436,6 +436,7 @@ struct brcmf_sdio_count {
struct brcmf_sdio {
struct brcmf_sdio_dev *sdiodev; /* sdio device handler */
struct brcmf_chip *ci; /* Chip info struct */
+ struct brcmf_core *sdio_core; /* sdio core info struct */
u32 hostintmask; /* Copy of Host Interrupt Mask */
atomic_t intstatus; /* Intstatus bits (events) pending */
@@ -665,10 +666,9 @@ static bool data_ok(struct brcmf_sdio *b
*/
static int r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
{
- struct brcmf_core *core;
+ struct brcmf_core *core = bus->sdio_core;
int ret;
- core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
*regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret);
return ret;
@@ -676,10 +676,9 @@ static int r_sdreg32(struct brcmf_sdio *
static int w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
{
- struct brcmf_core *core;
+ struct brcmf_core *core = bus->sdio_core;
int ret;
- core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret);
return ret;
@@ -2495,12 +2494,11 @@ static inline void brcmf_sdio_clrintr(st
static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
{
- struct brcmf_core *buscore;
+ struct brcmf_core *buscore = bus->sdio_core;
u32 addr;
unsigned long val;
int ret;
- buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
addr = buscore->base + SD_REG(intstatus);
val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
@@ -3377,13 +3375,14 @@ static void brcmf_sdio_sr_init(struct br
/* enable KSO bit */
static int brcmf_sdio_kso_init(struct brcmf_sdio *bus)
{
+ struct brcmf_core *core = bus->sdio_core;
u8 val;
int err = 0;
brcmf_dbg(TRACE, "Enter\n");
/* KSO bit added in SDIO core rev 12 */
- if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12)
+ if (core->rev < 12)
return 0;
val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
@@ -3412,6 +3411,7 @@ static int brcmf_sdio_bus_preinit(struct
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio *bus = sdiodev->bus;
+ struct brcmf_core *core = bus->sdio_core;
uint pad_size;
u32 value;
int err;
@@ -3420,7 +3420,7 @@ static int brcmf_sdio_bus_preinit(struct
* a device perspective, ie. bus:txglom affects the
* bus transfers from device to host.
*/
- if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12) {
+ if (core->rev < 12) {
/* for sdio core rev < 12, disable txgloming */
value = 0;
err = brcmf_iovar_data_set(dev, "bus:txglom", &value,
@@ -3758,11 +3758,10 @@ static void brcmf_sdio_buscore_activate(
u32 rstvec)
{
struct brcmf_sdio_dev *sdiodev = ctx;
- struct brcmf_core *core;
+ struct brcmf_core *core = sdiodev->bus->sdio_core;
u32 reg_addr;
/* clear all interrupts */
- core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV);
reg_addr = core->base + SD_REG(intstatus);
brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
@@ -3843,6 +3842,12 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
bus->ci = NULL;
goto fail;
}
+
+ /* Pick up the SDIO core info struct from chip.c */
+ bus->sdio_core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
+ if (!bus->sdio_core)
+ goto fail;
+
sdiodev->settings = brcmf_get_module_param(sdiodev->dev,
BRCMF_BUSTYPE_SDIO,
bus->ci->chip,

View file

@ -0,0 +1,44 @@
From 7762bb134e3b40e8ee2611365775b7432190a9c7 Mon Sep 17 00:00:00 2001
From: Wright Feng <wright.feng@cypress.com>
Date: Mon, 11 Dec 2017 15:38:21 +0800
Subject: [PATCH] brcmfmac: enlarge buffer size of caps to 512 bytes
The buffer size of return of cap iovar is greater than 256 bytes in some
firmwares. For instance, the return size of cap iovar is 271 bytes in 4373
13.10.246.79 firmare. It makes feature capability parsing failed because
caps buffer is default value.
So we enlarge caps buffer size to 512 bytes and add the error print for
cap iovar error.
Signed-off-by: Wright Feng <wright.feng@cypress.com>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -130,13 +130,19 @@ static void brcmf_feat_iovar_data_set(st
}
}
+#define MAX_CAPS_BUFFER_SIZE 512
static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
{
- char caps[256];
+ char caps[MAX_CAPS_BUFFER_SIZE];
enum brcmf_feat_id id;
- int i;
+ int i, err;
+
+ err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
+ if (err) {
+ brcmf_err("could not get firmware cap (%d)\n", err);
+ return;
+ }
- brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
brcmf_dbg(INFO, "[ %s]\n", caps);
for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) {

View file

@ -0,0 +1,227 @@
From 3d110df8f74781354051e4bb1e3e97fa368b2f80 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Tue, 19 Dec 2017 13:47:07 +0100
Subject: [PATCH] brcmfmac: Remove {r,w}_sdreg32
Remove yet another IO function from the code and replace with one
that already exists.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
[arend: keep address calculation, ie. (base + offset) in one line]
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 88 +++++++++++-----------
1 file changed, 42 insertions(+), 46 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -660,30 +660,6 @@ static bool data_ok(struct brcmf_sdio *b
((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
}
-/*
- * Reads a register in the SDIO hardware block. This block occupies a series of
- * adresses on the 32 bit backplane bus.
- */
-static int r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
-{
- struct brcmf_core *core = bus->sdio_core;
- int ret;
-
- *regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret);
-
- return ret;
-}
-
-static int w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
-{
- struct brcmf_core *core = bus->sdio_core;
- int ret;
-
- brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret);
-
- return ret;
-}
-
static int
brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
{
@@ -1078,6 +1054,8 @@ static void brcmf_sdio_get_console_addr(
static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
{
+ struct brcmf_sdio_dev *sdiod = bus->sdiodev;
+ struct brcmf_core *core = bus->sdio_core;
u32 intstatus = 0;
u32 hmb_data;
u8 fcbits;
@@ -1086,10 +1064,14 @@ static u32 brcmf_sdio_hostmail(struct br
brcmf_dbg(SDIO, "Enter\n");
/* Read mailbox data and ack that we did so */
- ret = r_sdreg32(bus, &hmb_data, SD_REG(tohostmailboxdata));
+ hmb_data = brcmf_sdiod_readl(sdiod,
+ core->base + SD_REG(tohostmailboxdata),
+ &ret);
+
+ if (!ret)
+ brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox),
+ SMB_INT_ACK, &ret);
- if (ret == 0)
- w_sdreg32(bus, SMB_INT_ACK, SD_REG(tosbmailbox));
bus->sdcnt.f1regdata += 2;
/* dongle indicates the firmware has halted/crashed */
@@ -1163,6 +1145,8 @@ static u32 brcmf_sdio_hostmail(struct br
static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
{
+ struct brcmf_sdio_dev *sdiod = bus->sdiodev;
+ struct brcmf_core *core = bus->sdio_core;
uint retries = 0;
u16 lastrbc;
u8 hi, lo;
@@ -1204,7 +1188,8 @@ static void brcmf_sdio_rxfail(struct brc
if (rtx) {
bus->sdcnt.rxrtx++;
- err = w_sdreg32(bus, SMB_NAK, SD_REG(tosbmailbox));
+ brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox),
+ SMB_NAK, &err);
bus->sdcnt.f1regdata++;
if (err == 0)
@@ -2291,6 +2276,7 @@ static uint brcmf_sdio_sendfromq(struct
{
struct sk_buff *pkt;
struct sk_buff_head pktq;
+ u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus);
u32 intstatus = 0;
int ret = 0, prec_out, i;
uint cnt = 0;
@@ -2329,7 +2315,8 @@ static uint brcmf_sdio_sendfromq(struct
if (!bus->intr) {
/* Check device status, signal pending interrupt */
sdio_claim_host(bus->sdiodev->func[1]);
- ret = r_sdreg32(bus, &intstatus, SD_REG(intstatus));
+ intstatus = brcmf_sdiod_readl(bus->sdiodev,
+ intstat_addr, &ret);
sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2txdata++;
if (ret != 0)
@@ -2413,12 +2400,13 @@ static int brcmf_sdio_tx_ctrlframe(struc
static void brcmf_sdio_bus_stop(struct device *dev)
{
- u32 local_hostintmask;
- u8 saveclk;
- int err;
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio *bus = sdiodev->bus;
+ struct brcmf_core *core = bus->sdio_core;
+ u32 local_hostintmask;
+ u8 saveclk;
+ int err;
brcmf_dbg(TRACE, "Enter\n");
@@ -2435,7 +2423,9 @@ static void brcmf_sdio_bus_stop(struct d
brcmf_sdio_bus_sleep(bus, false, false);
/* Disable and clear interrupts at the chip level also */
- w_sdreg32(bus, 0, SD_REG(hostintmask));
+ brcmf_sdiod_writel(sdiodev, core->base + SD_REG(hostintmask),
+ 0, NULL);
+
local_hostintmask = bus->hostintmask;
bus->hostintmask = 0;
@@ -2454,7 +2444,8 @@ static void brcmf_sdio_bus_stop(struct d
sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
/* Clear any pending interrupts now that F2 is disabled */
- w_sdreg32(bus, local_hostintmask, SD_REG(intstatus));
+ brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus),
+ local_hostintmask, NULL);
sdio_release_host(sdiodev->func[1]);
}
@@ -2521,7 +2512,9 @@ static int brcmf_sdio_intr_rstatus(struc
static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
{
+ struct brcmf_sdio_dev *sdiod = bus->sdiodev;
u32 newstatus = 0;
+ u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus);
unsigned long intstatus;
uint txlimit = bus->txbound; /* Tx frames to send before resched */
uint framecnt; /* Temporary counter of tx/rx frames */
@@ -2576,9 +2569,10 @@ static void brcmf_sdio_dpc(struct brcmf_
*/
if (intstatus & I_HMB_FC_CHANGE) {
intstatus &= ~I_HMB_FC_CHANGE;
- err = w_sdreg32(bus, I_HMB_FC_CHANGE, SD_REG(intstatus));
+ brcmf_sdiod_writel(sdiod, intstat_addr, I_HMB_FC_CHANGE, &err);
+
+ newstatus = brcmf_sdiod_readl(sdiod, intstat_addr, &err);
- err = r_sdreg32(bus, &newstatus, SD_REG(intstatus));
bus->sdcnt.f1regdata += 2;
atomic_set(&bus->fcstate,
!!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)));
@@ -4017,22 +4011,21 @@ static void brcmf_sdio_firmware_callback
const struct firmware *code,
void *nvram, u32 nvram_len)
{
- struct brcmf_bus *bus_if;
- struct brcmf_sdio_dev *sdiodev;
- struct brcmf_sdio *bus;
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+ struct brcmf_sdio *bus = sdiodev->bus;
+ struct brcmf_sdio_dev *sdiod = bus->sdiodev;
+ struct brcmf_core *core = bus->sdio_core;
u8 saveclk;
brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
- bus_if = dev_get_drvdata(dev);
- sdiodev = bus_if->bus_priv.sdio;
+
if (err)
goto fail;
if (!bus_if->drvr)
return;
- bus = sdiodev->bus;
-
/* try to download image and nvram to the dongle */
bus->alp_only = true;
err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
@@ -4063,8 +4056,9 @@ static void brcmf_sdio_firmware_callback
}
/* Enable function 2 (frame transfers) */
- w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
- SD_REG(tosbmailboxdata));
+ brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata),
+ SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL);
+
err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
@@ -4074,7 +4068,9 @@ static void brcmf_sdio_firmware_callback
if (!err) {
/* Set up the interrupt mask and enable interrupts */
bus->hostintmask = HOSTINTMASK;
- w_sdreg32(bus, bus->hostintmask, SD_REG(hostintmask));
+ brcmf_sdiod_writel(sdiod, core->base + SD_REG(hostintmask),
+ bus->hostintmask, NULL);
+
brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
} else {

View file

@ -0,0 +1,33 @@
From dbda7dacb79a377e8ed9d38ce0e4a58b70aa9060 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Tue, 19 Dec 2017 13:47:08 +0100
Subject: [PATCH] brcmfmac: Rename buscore to core for consistency
Avoid confusion with unrelated _buscore labels.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
[arend: only do the rename]
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -2485,12 +2485,12 @@ static inline void brcmf_sdio_clrintr(st
static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
{
- struct brcmf_core *buscore = bus->sdio_core;
+ struct brcmf_core *core = bus->sdio_core;
u32 addr;
unsigned long val;
int ret;
- addr = buscore->base + SD_REG(intstatus);
+ addr = core->base + SD_REG(intstatus);
val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
bus->sdcnt.f1regdata++;

View file

@ -0,0 +1,82 @@
From 874bb8e49b7c6368f8ff9f2566c7bd06a2249be0 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Tue, 19 Dec 2017 13:47:09 +0100
Subject: [PATCH] brcmfmac: stabilise the value of ->sbwad in use for some xfer
routines.
The IO functions operate within the Chipcommon IO window. Explicitly
set this, rather than relying on the last initialisation IO access to
leave it set to the right value by chance.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 8 ++++----
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 5 +++++
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 +
3 files changed, 10 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -529,7 +529,7 @@ int brcmf_sdiod_recv_buf(struct brcmf_sd
int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt)
{
- u32 addr = sdiodev->sbwad;
+ u32 addr = sdiodev->cc_core->base;
int err = 0;
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
@@ -552,7 +552,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_
{
struct sk_buff *glom_skb = NULL;
struct sk_buff *skb;
- u32 addr = sdiodev->sbwad;
+ u32 addr = sdiodev->cc_core->base;
int err = 0;
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n",
@@ -593,7 +593,7 @@ done:
int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
{
struct sk_buff *mypkt;
- u32 addr = sdiodev->sbwad;
+ u32 addr = sdiodev->cc_core->base;
int err;
mypkt = brcmu_pkt_buf_get_skb(nbytes);
@@ -625,7 +625,7 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
struct sk_buff_head *pktq)
{
struct sk_buff *skb;
- u32 addr = sdiodev->sbwad;
+ u32 addr = sdiodev->cc_core->base;
int err;
brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3842,6 +3842,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
if (!bus->sdio_core)
goto fail;
+ /* Pick up the CHIPCOMMON core info struct, for bulk IO in bcmsdh.c */
+ sdiodev->cc_core = brcmf_chip_get_core(bus->ci, BCMA_CORE_CHIPCOMMON);
+ if (!sdiodev->cc_core)
+ goto fail;
+
sdiodev->settings = brcmf_get_module_param(sdiodev->dev,
BRCMF_BUSTYPE_SDIO,
bus->ci->chip,
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -178,6 +178,7 @@ struct brcmf_sdio_dev {
struct sdio_func *func[SDIO_MAX_FUNCS];
u8 num_funcs; /* Supported funcs on client */
u32 sbwad; /* Save backplane window address */
+ struct brcmf_core *cc_core; /* chipcommon core info struct */
struct brcmf_sdio *bus;
struct device *dev;
struct brcmf_bus *bus_if;

View file

@ -0,0 +1,45 @@
From 508422f3695bf66f7b85fb4723c22f5166003ec6 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Tue, 19 Dec 2017 13:47:10 +0100
Subject: [PATCH] brcmfmac: Correctly handle accesses to SDIO func0
Rather than workaround the restrictions on func0 addressing in the
driver, set MMC_QUIRK_LENIENT_FN0
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 4 ++++
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 4 ++--
2 files changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -995,6 +995,10 @@ static int brcmf_ops_sdio_probe(struct s
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
dev = &func->dev;
+
+ /* Set MMC_QUIRK_LENIENT_FN0 for this card */
+ func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+
/* prohibit ACPI power management for this device */
brcmf_sdiod_acpi_set_power_manageable(dev, 0);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -297,10 +297,10 @@ void brcmf_sdiod_intr_unregister(struct
/* SDIO device register access interface */
/* Accessors for SDIO Function 0 */
#define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
- sdio_readb((sdiodev)->func[0], (addr), (r))
+ sdio_f0_readb((sdiodev)->func[0], (addr), (r))
#define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
- sdio_writeb((sdiodev)->func[0], (v), (addr), (ret))
+ sdio_f0_writeb((sdiodev)->func[0], (v), (addr), (ret))
/* Accessors for SDIO Function 1 */
#define brcmf_sdiod_readb(sdiodev, addr, r) \

View file

@ -0,0 +1,111 @@
From 99d7b6fdfc8c24052c92c720330d31ca1332f996 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Tue, 19 Dec 2017 13:47:11 +0100
Subject: [PATCH] brcmfmac: Remove func0 from function array
func0 is not provided by the mmc stack as a function when probing.
Instead providing specific access functions to read/write it.
This prepares for a patch to remove the actual array entry itself.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
[arend: rephrased the commit message]
[arend: removed unrelated comment for which separate patch is warranted]
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 +----
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 ++++---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 13 ++++++-------
3 files changed, 11 insertions(+), 14 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -1022,8 +1022,7 @@ static int brcmf_ops_sdio_probe(struct s
/* store refs to functions used. mmc_card does
* not hold the F0 function pointer.
*/
- sdiodev->func[0] = kmemdup(func, sizeof(*func), GFP_KERNEL);
- sdiodev->func[0]->num = 0;
+ sdiodev->func[0] = NULL;
sdiodev->func[1] = func->card->sdio_func[0];
sdiodev->func[2] = func;
@@ -1049,7 +1048,6 @@ static int brcmf_ops_sdio_probe(struct s
fail:
dev_set_drvdata(&func->dev, NULL);
dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
- kfree(sdiodev->func[0]);
kfree(sdiodev);
kfree(bus_if);
return err;
@@ -1082,7 +1080,6 @@ static void brcmf_ops_sdio_remove(struct
dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
kfree(bus_if);
- kfree(sdiodev->func[0]);
kfree(sdiodev);
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3771,9 +3771,10 @@ static u32 brcmf_sdio_buscore_read32(voi
u32 val, rev;
val = brcmf_sdiod_readl(sdiodev, addr, NULL);
- if ((sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
- sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
- addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
+
+ if ((sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
+ sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
+ addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
if (rev >= 2) {
val &= ~CID_ID_MASK;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -21,7 +21,9 @@
#include <linux/firmware.h>
#include "firmware.h"
-#define SDIO_FUNC_0 0
+/* Maximum number of I/O funcs */
+#define NUM_SDIO_FUNCS 3
+
#define SDIO_FUNC_1 1
#define SDIO_FUNC_2 2
@@ -39,9 +41,6 @@
#define INTR_STATUS_FUNC1 0x2
#define INTR_STATUS_FUNC2 0x4
-/* Maximum number of I/O funcs */
-#define SDIOD_MAX_IOFUNCS 7
-
/* mask of register map */
#define REG_F0_REG_MASK 0x7FF
#define REG_F1_MISC_MASK 0x1FFFF
@@ -175,7 +174,7 @@ struct brcmf_sdio;
struct brcmf_sdiod_freezer;
struct brcmf_sdio_dev {
- struct sdio_func *func[SDIO_MAX_FUNCS];
+ struct sdio_func *func[NUM_SDIO_FUNCS];
u8 num_funcs; /* Supported funcs on client */
u32 sbwad; /* Save backplane window address */
struct brcmf_core *cc_core; /* chipcommon core info struct */
@@ -297,10 +296,10 @@ void brcmf_sdiod_intr_unregister(struct
/* SDIO device register access interface */
/* Accessors for SDIO Function 0 */
#define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
- sdio_f0_readb((sdiodev)->func[0], (addr), (r))
+ sdio_f0_readb((sdiodev)->func[1], (addr), (r))
#define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
- sdio_f0_writeb((sdiodev)->func[0], (v), (addr), (ret))
+ sdio_f0_writeb((sdiodev)->func[1], (v), (addr), (ret))
/* Accessors for SDIO Function 1 */
#define brcmf_sdiod_readb(sdiodev, addr, r) \

View file

@ -0,0 +1,40 @@
From bcadaaa097c7ec103fe75f9da41f8fe52693b644 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Tue, 19 Dec 2017 13:47:12 +0100
Subject: [PATCH] brcmfmac: More efficient and slightly easier to read fixup
for 4339 chips
Its more efficient to test the register we're interested in first,
potentially avoiding two more comparisons, and therefore always avoiding
one comparison per call on all other chips.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
[arend: fix some checkpatch warnings]
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3772,15 +3772,16 @@ static u32 brcmf_sdio_buscore_read32(voi
val = brcmf_sdiod_readl(sdiodev, addr, NULL);
- if ((sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
- sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
- addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
+ if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) &&
+ (sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339 ||
+ sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) {
rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
if (rev >= 2) {
val &= ~CID_ID_MASK;
val |= BRCM_CC_4339_CHIP_ID;
}
}
+
return val;
}

View file

@ -0,0 +1,347 @@
From 00eb62cfc5f806b003fe5d54c8b5fe9a9665482f Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Tue, 19 Dec 2017 13:47:13 +0100
Subject: [PATCH] brcmfmac: Replace function index with function pointer
In preparation for removing the function array, remove all code that
refers to function by index and replace with pointers to the function
itself.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
[arend: replace BUG() with WARN() macro]
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 85 ++++++++++++----------
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 15 ++--
.../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 6 +-
3 files changed, 56 insertions(+), 50 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -291,8 +291,9 @@ out:
*ret = retval;
}
-static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev, uint fn,
- u32 addr, struct sk_buff *pkt)
+static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev,
+ struct sdio_func *func, u32 addr,
+ struct sk_buff *pkt)
{
unsigned int req_sz;
int err;
@@ -301,13 +302,19 @@ static int brcmf_sdiod_buff_read(struct
req_sz = pkt->len + 3;
req_sz &= (uint)~3;
- if (fn == 1)
- err = sdio_memcpy_fromio(sdiodev->func[fn],
- ((u8 *)(pkt->data)), addr, req_sz);
- else
- /* function 2 read is FIFO operation */
- err = sdio_readsb(sdiodev->func[fn],
- ((u8 *)(pkt->data)), addr, req_sz);
+ switch (func->num) {
+ case 1:
+ err = sdio_memcpy_fromio(func, ((u8 *)(pkt->data)), addr,
+ req_sz);
+ break;
+ case 2:
+ err = sdio_readsb(func, ((u8 *)(pkt->data)), addr, req_sz);
+ break;
+ default:
+ /* bail out as things are really fishy here */
+ WARN(1, "invalid sdio function number: %d\n", func->num);
+ err = -ENOMEDIUM;
+ };
if (err == -ENOMEDIUM)
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
@@ -315,8 +322,9 @@ static int brcmf_sdiod_buff_read(struct
return err;
}
-static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev, uint fn,
- u32 addr, struct sk_buff *pkt)
+static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev,
+ struct sdio_func *func, u32 addr,
+ struct sk_buff *pkt)
{
unsigned int req_sz;
int err;
@@ -325,8 +333,7 @@ static int brcmf_sdiod_buff_write(struct
req_sz = pkt->len + 3;
req_sz &= (uint)~3;
- err = sdio_memcpy_toio(sdiodev->func[fn], addr,
- ((u8 *)(pkt->data)), req_sz);
+ err = sdio_memcpy_toio(func, addr, ((u8 *)(pkt->data)), req_sz);
if (err == -ENOMEDIUM)
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
@@ -337,7 +344,7 @@ static int brcmf_sdiod_buff_write(struct
/**
* brcmf_sdiod_sglist_rw - SDIO interface function for block data access
* @sdiodev: brcmfmac sdio device
- * @fn: SDIO function number
+ * @func: SDIO function
* @write: direction flag
* @addr: dongle memory address as source/destination
* @pkt: skb pointer
@@ -346,7 +353,8 @@ static int brcmf_sdiod_buff_write(struct
* stack for block data access. It assumes that the skb passed down by the
* caller has already been padded and aligned.
*/
-static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
+static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev,
+ struct sdio_func *func,
bool write, u32 addr,
struct sk_buff_head *pktlist)
{
@@ -372,7 +380,7 @@ static int brcmf_sdiod_sglist_rw(struct
req_sz = 0;
skb_queue_walk(pktlist, pkt_next)
req_sz += pkt_next->len;
- req_sz = ALIGN(req_sz, sdiodev->func[fn]->cur_blksize);
+ req_sz = ALIGN(req_sz, func->cur_blksize);
while (req_sz > PAGE_SIZE) {
pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE);
if (pkt_next == NULL) {
@@ -391,7 +399,7 @@ static int brcmf_sdiod_sglist_rw(struct
target_list = &local_list;
}
- func_blk_sz = sdiodev->func[fn]->cur_blksize;
+ func_blk_sz = func->cur_blksize;
max_req_sz = sdiodev->max_request_size;
max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count,
target_list->qlen);
@@ -408,10 +416,10 @@ static int brcmf_sdiod_sglist_rw(struct
mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
mmc_cmd.opcode = SD_IO_RW_EXTENDED;
mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */
- mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */
- mmc_cmd.arg |= 1<<27; /* block mode */
+ mmc_cmd.arg |= (func->num & 0x7) << 28; /* SDIO func num */
+ mmc_cmd.arg |= 1 << 27; /* block mode */
/* for function 1 the addr will be incremented */
- mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0;
+ mmc_cmd.arg |= (func->num == 1) ? 1 << 26 : 0;
mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
mmc_req.cmd = &mmc_cmd;
mmc_req.data = &mmc_dat;
@@ -457,11 +465,11 @@ static int brcmf_sdiod_sglist_rw(struct
mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */
mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */
/* incrementing addr for function 1 */
- if (fn == 1)
+ if (func->num == 1)
addr += req_sz;
- mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card);
- mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req);
+ mmc_set_data_timeout(&mmc_dat, func->card);
+ mmc_wait_for_req(func->card->host, &mmc_req);
ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
if (ret == -ENOMEDIUM) {
@@ -541,7 +549,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
addr &= SBSDIO_SB_OFT_ADDR_MASK;
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt);
+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, pkt);
done:
return err;
@@ -566,13 +574,13 @@ int brcmf_sdiod_recv_chain(struct brcmf_
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
if (pktq->qlen == 1)
- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr,
pktq->next);
else if (!sdiodev->sg_support) {
glom_skb = brcmu_pkt_buf_get_skb(totlen);
if (!glom_skb)
return -ENOMEM;
- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr,
glom_skb);
if (err)
goto done;
@@ -582,8 +590,8 @@ int brcmf_sdiod_recv_chain(struct brcmf_
skb_pull(glom_skb, skb->len);
}
} else
- err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, false, addr,
- pktq);
+ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], false,
+ addr, pktq);
done:
brcmu_pkt_buf_free_skb(glom_skb);
@@ -614,7 +622,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
if (!err)
- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt);
+ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2], addr,
+ mypkt);
brcmu_pkt_buf_free_skb(mypkt);
@@ -639,14 +648,14 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
if (pktq->qlen == 1 || !sdiodev->sg_support) {
skb_queue_walk(pktq, skb) {
- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2,
+ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2],
addr, skb);
if (err)
break;
}
} else {
- err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr,
- pktq);
+ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], true,
+ addr, pktq);
}
return err;
@@ -696,10 +705,10 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
if (write) {
memcpy(pkt->data, data, dsize);
- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_1,
+ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[1],
sdaddr, pkt);
} else {
- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_1,
+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[1],
sdaddr, pkt);
}
@@ -728,12 +737,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
return err;
}
-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)
+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func)
{
brcmf_dbg(SDIO, "Enter\n");
/* Issue abort cmd52 command through F0 */
- brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, fn, NULL);
+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, func->num, NULL);
brcmf_dbg(SDIO, "Exit\n");
return 0;
@@ -1105,7 +1114,7 @@ static int brcmf_ops_sdio_suspend(struct
func = container_of(dev, struct sdio_func, dev);
brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
- if (func->num != SDIO_FUNC_1)
+ if (func->num != 1)
return 0;
@@ -1134,7 +1143,7 @@ static int brcmf_ops_sdio_resume(struct
struct sdio_func *func = container_of(dev, struct sdio_func, dev);
brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
- if (func->num != SDIO_FUNC_2)
+ if (func->num != 2)
return 0;
brcmf_sdiod_freezer_off(sdiodev);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -1157,7 +1157,7 @@ static void brcmf_sdio_rxfail(struct brc
rtx ? ", send NAK" : "");
if (abort)
- brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
+ brcmf_sdiod_abort(bus->sdiodev, bus->sdiodev->func[2]);
brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
&err);
@@ -1209,7 +1209,7 @@ static void brcmf_sdio_txfail(struct brc
brcmf_err("sdio error, abort command and terminate frame\n");
bus->sdcnt.tx_sderrs++;
- brcmf_sdiod_abort(sdiodev, SDIO_FUNC_2);
+ brcmf_sdiod_abort(sdiodev, sdiodev->func[2]);
brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
bus->sdcnt.f1regdata++;
@@ -2072,7 +2072,7 @@ static int brcmf_sdio_txpkt_prep_sg(stru
int ntail, ret;
sdiodev = bus->sdiodev;
- blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize;
+ blksize = sdiodev->func[2]->cur_blksize;
/* sg entry alignment should be a divisor of block size */
WARN_ON(blksize % bus->sgentry_align);
@@ -2441,7 +2441,7 @@ static void brcmf_sdio_bus_stop(struct d
/* Turn off the bus (F2), free any pending packets */
brcmf_dbg(INTR, "disable SDIO interrupts\n");
- sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
+ sdio_disable_func(sdiodev->func[2]);
/* Clear any pending interrupts now that F2 is disabled */
brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus),
@@ -4066,8 +4066,7 @@ static void brcmf_sdio_firmware_callback
brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata),
SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL);
- err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
-
+ err = sdio_enable_func(sdiodev->func[2]);
brcmf_dbg(INFO, "enable F2: err=%d\n", err);
@@ -4082,7 +4081,7 @@ static void brcmf_sdio_firmware_callback
brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
} else {
/* Disable F2 again */
- sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
+ sdio_disable_func(sdiodev->func[2]);
goto release;
}
@@ -4219,7 +4218,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
sdio_claim_host(bus->sdiodev->func[1]);
/* Disable F2 to clear any intermediate frame state on the dongle */
- sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
+ sdio_disable_func(bus->sdiodev->func[2]);
bus->rxflow = false;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -45,9 +45,6 @@
#define REG_F0_REG_MASK 0x7FF
#define REG_F1_MISC_MASK 0x1FFFF
-/* as of sdiod rev 0, supports 3 functions */
-#define SBSDIO_NUM_FUNCTION 3
-
/* function 0 vendor specific CCCR registers */
#define SDIO_CCCR_BRCM_CARDCAP 0xf0
@@ -350,7 +347,8 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
u8 *data, uint size);
/* Issue an abort to the specified function */
-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn);
+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func);
+
void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
enum brcmf_sdiod_state state);

View file

@ -0,0 +1,53 @@
From 9c3438ed215adba7025268ee1f0b6f7a2af12316 Mon Sep 17 00:00:00 2001
From: Ian Molton <ian@mnementh.co.uk>
Date: Tue, 19 Dec 2017 13:47:14 +0100
Subject: [PATCH] brcmfmac: Clean up interrupt macros
Make it more obvious that this code acually enables interrupts, and
provide nice definitions for the bits in the register.
Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 3 ++-
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 8 +++++---
2 files changed, 7 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -149,7 +149,8 @@ int brcmf_sdiod_intr_register(struct brc
/* must configure SDIO_CCCR_IENx to enable irq */
data = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_IENx, &ret);
- data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
+ data |= SDIO_CCCR_IEN_FUNC1 | SDIO_CCCR_IEN_FUNC2 |
+ SDIO_CCCR_IEN_FUNC0;
brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret);
/* redirect, configure and enable io for interrupt signal */
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -24,9 +24,6 @@
/* Maximum number of I/O funcs */
#define NUM_SDIO_FUNCS 3
-#define SDIO_FUNC_1 1
-#define SDIO_FUNC_2 2
-
#define SDIOD_FBR_SIZE 0x100
/* io_en */
@@ -52,6 +49,11 @@
#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT BIT(2)
#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC BIT(3)
+/* Interrupt enable bits for each function */
+#define SDIO_CCCR_IEN_FUNC0 BIT(0)
+#define SDIO_CCCR_IEN_FUNC1 BIT(1)
+#define SDIO_CCCR_IEN_FUNC2 BIT(2)
+
#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET BIT(1)

View file

@ -0,0 +1,27 @@
From e3720dad99859251a8b0fe2807275a8afcfb560d Mon Sep 17 00:00:00 2001
From: Double Lo <double.lo@cypress.com>
Date: Tue, 19 Dec 2017 14:56:44 +0800
Subject: [PATCH] brcmfmac: Support 43455 save-restore (SR) feature if FW
include -sr
This patch will add 43455 into the save-restore(SR) capable chip list, so
the SR engine will be enabled with 43455 FW which built-in the -sr
function.
Signed-off-by: Double Lo <double.lo@cypress.com>
Signed-off-by: Wright Feng <wright.feng@cypress.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -1338,6 +1338,7 @@ bool brcmf_chip_sr_capable(struct brcmf_
switch (pub->chip) {
case BRCM_CC_4354_CHIP_ID:
case BRCM_CC_4356_CHIP_ID:
+ case BRCM_CC_4345_CHIP_ID:
/* explicitly check SR engine enable bit */
pmu_cc3_mask = BIT(2);
/* fall-through */

View file

@ -0,0 +1,31 @@
From 32adbcaa5df49f1977441f7a4bf180a0bcfe9966 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Tue, 9 Jan 2018 13:22:53 +0100
Subject: [PATCH] brcmfmac: add comment block in brcmf_sdio_buscore_read()
In brcmf_sdio_buscore_read() there is some special handling upon
register access to chipid register of the chipcommon core. Add
comment explaining why it is done here.
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3772,6 +3772,13 @@ static u32 brcmf_sdio_buscore_read32(voi
val = brcmf_sdiod_readl(sdiodev, addr, NULL);
+ /*
+ * this is a bit of special handling if reading the chipcommon chipid
+ * register. The 4339 is a next-gen of the 4335. It uses the same
+ * SDIO device id as 4335 and the chipid register returns 4335 as well.
+ * It can be identified as 4339 by looking at the chip revision. It
+ * is corrected here so the chip.c module has the right info.
+ */
if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) &&
(sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4339 ||
sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) {

View file

@ -0,0 +1,137 @@
From 378f6a16043e5d3346301fc618f503e97aea335b Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Tue, 9 Jan 2018 13:22:54 +0100
Subject: [PATCH] brcmfmac: rename brcmf_sdiod_buff_{read,write}() functions
Rename functions to brcmf_sdio_skbuff_{read,write}() as we pass an
skbuff to this function.
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 48 +++++++++++-----------
1 file changed, 24 insertions(+), 24 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -292,24 +292,24 @@ out:
*ret = retval;
}
-static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev,
- struct sdio_func *func, u32 addr,
- struct sk_buff *pkt)
+static int brcmf_sdiod_skbuff_read(struct brcmf_sdio_dev *sdiodev,
+ struct sdio_func *func, u32 addr,
+ struct sk_buff *skb)
{
unsigned int req_sz;
int err;
/* Single skb use the standard mmc interface */
- req_sz = pkt->len + 3;
+ req_sz = skb->len + 3;
req_sz &= (uint)~3;
switch (func->num) {
case 1:
- err = sdio_memcpy_fromio(func, ((u8 *)(pkt->data)), addr,
+ err = sdio_memcpy_fromio(func, ((u8 *)(skb->data)), addr,
req_sz);
break;
case 2:
- err = sdio_readsb(func, ((u8 *)(pkt->data)), addr, req_sz);
+ err = sdio_readsb(func, ((u8 *)(skb->data)), addr, req_sz);
break;
default:
/* bail out as things are really fishy here */
@@ -323,18 +323,18 @@ static int brcmf_sdiod_buff_read(struct
return err;
}
-static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev,
- struct sdio_func *func, u32 addr,
- struct sk_buff *pkt)
+static int brcmf_sdiod_skbuff_write(struct brcmf_sdio_dev *sdiodev,
+ struct sdio_func *func, u32 addr,
+ struct sk_buff *skb)
{
unsigned int req_sz;
int err;
/* Single skb use the standard mmc interface */
- req_sz = pkt->len + 3;
+ req_sz = skb->len + 3;
req_sz &= (uint)~3;
- err = sdio_memcpy_toio(func, addr, ((u8 *)(pkt->data)), req_sz);
+ err = sdio_memcpy_toio(func, addr, ((u8 *)(skb->data)), req_sz);
if (err == -ENOMEDIUM)
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
@@ -550,7 +550,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
addr &= SBSDIO_SB_OFT_ADDR_MASK;
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr, pkt);
+ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr, pkt);
done:
return err;
@@ -575,14 +575,14 @@ int brcmf_sdiod_recv_chain(struct brcmf_
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
if (pktq->qlen == 1)
- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr,
- pktq->next);
+ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr,
+ pktq->next);
else if (!sdiodev->sg_support) {
glom_skb = brcmu_pkt_buf_get_skb(totlen);
if (!glom_skb)
return -ENOMEM;
- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr,
- glom_skb);
+ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr,
+ glom_skb);
if (err)
goto done;
@@ -623,8 +623,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
if (!err)
- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2, addr,
- mypkt);
+ err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr,
+ mypkt);
brcmu_pkt_buf_free_skb(mypkt);
@@ -649,8 +649,8 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
if (pktq->qlen == 1 || !sdiodev->sg_support) {
skb_queue_walk(pktq, skb) {
- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2,
- addr, skb);
+ err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2,
+ addr, skb);
if (err)
break;
}
@@ -706,11 +706,11 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
if (write) {
memcpy(pkt->data, data, dsize);
- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func1,
- sdaddr, pkt);
+ err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func1,
+ sdaddr, pkt);
} else {
- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func1,
- sdaddr, pkt);
+ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func1,
+ sdaddr, pkt);
}
if (err) {

View file

@ -0,0 +1,59 @@
From b7acadaf038740c43515dc1548f43d01cc92823a Mon Sep 17 00:00:00 2001
From: Himanshu Jha <himanshujha199640@gmail.com>
Date: Tue, 9 Jan 2018 02:15:31 +0530
Subject: [PATCH] brcmfmac: Use zeroing memory allocator than allocator/memset
Use dma_zalloc_coherent for allocating zeroed
memory and remove unnecessary memset function.
Generated-by: scripts/coccinelle/api/alloc/kzalloc-simple.cocci
Suggested-by: Luis R. Rodriguez <mcgrof@kernel.org>
Signed-off-by: Himanshu Jha <himanshujha199640@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -1251,14 +1251,14 @@ static int brcmf_pcie_init_scratchbuffer
u64 address;
u32 addr;
- devinfo->shared.scratch = dma_alloc_coherent(&devinfo->pdev->dev,
- BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
- &devinfo->shared.scratch_dmahandle, GFP_KERNEL);
+ devinfo->shared.scratch =
+ dma_zalloc_coherent(&devinfo->pdev->dev,
+ BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+ &devinfo->shared.scratch_dmahandle,
+ GFP_KERNEL);
if (!devinfo->shared.scratch)
goto fail;
- memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
-
addr = devinfo->shared.tcm_base_address +
BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
address = (u64)devinfo->shared.scratch_dmahandle;
@@ -1268,14 +1268,14 @@ static int brcmf_pcie_init_scratchbuffer
BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET;
brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
- devinfo->shared.ringupd = dma_alloc_coherent(&devinfo->pdev->dev,
- BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
- &devinfo->shared.ringupd_dmahandle, GFP_KERNEL);
+ devinfo->shared.ringupd =
+ dma_zalloc_coherent(&devinfo->pdev->dev,
+ BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+ &devinfo->shared.ringupd_dmahandle,
+ GFP_KERNEL);
if (!devinfo->shared.ringupd)
goto fail;
- memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
-
addr = devinfo->shared.tcm_base_address +
BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
address = (u64)devinfo->shared.ringupd_dmahandle;

View file

@ -0,0 +1,26 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 9 Feb 2018 19:46:54 +0100
Subject: [PATCH] mac80211: round IEEE80211_TX_STATUS_HEADROOM up to multiple
of 4
This ensures that mac80211 allocated management frames are properly
aligned, which makes copying them more efficient.
For instance, mt76 uses iowrite32_copy to copy beacon frames to beacon
template memory on the chip.
Misaligned 32-bit accesses cause CPU exceptions on MIPS and should be
avoided.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4145,7 +4145,7 @@ void ieee80211_sta_uapsd_trigger(struct
* The TX headroom reserved by mac80211 for its own tx_status functions.
* This is enough for the radiotap header.
*/
-#define IEEE80211_TX_STATUS_HEADROOM 14
+#define IEEE80211_TX_STATUS_HEADROOM ALIGN(14, 4)
/**
* ieee80211_sta_set_buffered - inform mac80211 about driver-buffered frames

View file

@ -0,0 +1,21 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 23 Feb 2018 09:59:35 +0100
Subject: [PATCH] mac80211: drop frames with unexpected DS bits from
fast-rx to slow path
Fixes rx for 4-addr packets in AP mode
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3928,7 +3928,7 @@ static bool ieee80211_invoke_fast_rx(str
if ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FROMDS |
IEEE80211_FCTL_TODS)) !=
fast_rx->expected_ds_bits)
- goto drop;
+ return false;
/* assign the key to drop unencrypted frames (later)
* and strip the IV/MIC if necessary

View file

@ -0,0 +1,25 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 23 Feb 2018 10:00:22 +0100
Subject: [PATCH] mac80211: support AP 4-addr mode fast-rx
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3774,6 +3774,15 @@ void ieee80211_check_fast_rx(struct sta_
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN ||
!sdata->u.vlan.sta);
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+ sdata->u.vlan.sta) {
+ fastrx.expected_ds_bits |=
+ cpu_to_le16(IEEE80211_FCTL_FROMDS);
+ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
+ fastrx.internal_forward = 0;
+ }
+
break;
default:
goto clear;

View file

@ -0,0 +1,53 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 23 Feb 2018 10:01:53 +0100
Subject: [PATCH] mac80211: support fast-rx with incompatible PS
capabilities when PS is disabled
When powersave is disabled for the interface, we can do fast-rx anyway.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2658,6 +2658,7 @@ static int ieee80211_set_power_mgmt(stru
ieee80211_recalc_ps(local);
ieee80211_recalc_ps_vif(sdata);
+ ieee80211_check_fast_rx_iface(sdata);
return 0;
}
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3741,12 +3741,7 @@ void ieee80211_check_fast_rx(struct sta_
/* 4-addr is harder to deal with, later maybe */
if (sdata->u.mgd.use_4addr)
goto clear;
- /* software powersave is a huge mess, avoid all of it */
- if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK))
- goto clear;
- if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) &&
- !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
- goto clear;
+
if (sta->sta.tdls) {
fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1);
fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2);
@@ -3758,6 +3753,16 @@ void ieee80211_check_fast_rx(struct sta_
fastrx.expected_ds_bits =
cpu_to_le16(IEEE80211_FCTL_FROMDS);
}
+
+ if (!sdata->u.mgd.powersave)
+ break;
+
+ /* software powersave is a huge mess, avoid all of it */
+ if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK))
+ goto clear;
+ if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) &&
+ !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
+ goto clear;
break;
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_AP:

View file

@ -0,0 +1,34 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 23 Feb 2018 10:05:08 +0100
Subject: [PATCH] mac80211: support station 4-addr mode fast-rx
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3738,10 +3738,6 @@ void ieee80211_check_fast_rx(struct sta_
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
- /* 4-addr is harder to deal with, later maybe */
- if (sdata->u.mgd.use_4addr)
- goto clear;
-
if (sta->sta.tdls) {
fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1);
fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2);
@@ -3754,6 +3750,13 @@ void ieee80211_check_fast_rx(struct sta_
cpu_to_le16(IEEE80211_FCTL_FROMDS);
}
+ if (sdata->u.mgd.use_4addr && !sta->sta.tdls) {
+ fastrx.expected_ds_bits |=
+ cpu_to_le16(IEEE80211_FCTL_TODS);
+ fastrx.da_offs = offsetof(struct ieee80211_hdr, addr3);
+ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
+ }
+
if (!sdata->u.mgd.powersave)
break;

View file

@ -0,0 +1,256 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 26 Feb 2018 22:09:29 +0100
Subject: [PATCH] mac80211: support A-MSDU in fast-rx
Only works if the IV was stripped from packets. Create a smaller
variant of ieee80211_rx_h_amsdu, which bypasses checks already done
within the fast-rx context.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2358,39 +2358,17 @@ ieee80211_deliver_skb(struct ieee80211_r
}
static ieee80211_rx_result debug_noinline
-ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
+__ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
{
struct net_device *dev = rx->sdata->dev;
struct sk_buff *skb = rx->skb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
struct sk_buff_head frame_list;
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
struct ethhdr ethhdr;
const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
- if (unlikely(!ieee80211_is_data(fc)))
- return RX_CONTINUE;
-
- if (unlikely(!ieee80211_is_data_present(fc)))
- return RX_DROP_MONITOR;
-
- if (!(status->rx_flags & IEEE80211_RX_AMSDU))
- return RX_CONTINUE;
-
if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
- switch (rx->sdata->vif.type) {
- case NL80211_IFTYPE_AP_VLAN:
- if (!rx->sdata->u.vlan.sta)
- return RX_DROP_UNUSABLE;
- break;
- case NL80211_IFTYPE_STATION:
- if (!rx->sdata->u.mgd.use_4addr)
- return RX_DROP_UNUSABLE;
- break;
- default:
- return RX_DROP_UNUSABLE;
- }
check_da = NULL;
check_sa = NULL;
} else switch (rx->sdata->vif.type) {
@@ -2410,15 +2388,13 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
break;
}
- if (is_multicast_ether_addr(hdr->addr1))
- return RX_DROP_UNUSABLE;
-
skb->dev = dev;
__skb_queue_head_init(&frame_list);
if (ieee80211_data_to_8023_exthdr(skb, &ethhdr,
rx->sdata->vif.addr,
- rx->sdata->vif.type))
+ rx->sdata->vif.type,
+ data_offset))
return RX_DROP_UNUSABLE;
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
@@ -2440,6 +2416,44 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
return RX_QUEUED;
}
+static ieee80211_rx_result debug_noinline
+ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
+{
+ struct sk_buff *skb = rx->skb;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ __le16 fc = hdr->frame_control;
+
+ if (!(status->rx_flags & IEEE80211_RX_AMSDU))
+ return RX_CONTINUE;
+
+ if (unlikely(!ieee80211_is_data(fc)))
+ return RX_CONTINUE;
+
+ if (unlikely(!ieee80211_is_data_present(fc)))
+ return RX_DROP_MONITOR;
+
+ if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
+ switch (rx->sdata->vif.type) {
+ case NL80211_IFTYPE_AP_VLAN:
+ if (!rx->sdata->u.vlan.sta)
+ return RX_DROP_UNUSABLE;
+ break;
+ case NL80211_IFTYPE_STATION:
+ if (!rx->sdata->u.mgd.use_4addr)
+ return RX_DROP_UNUSABLE;
+ break;
+ default:
+ return RX_DROP_UNUSABLE;
+ }
+ }
+
+ if (is_multicast_ether_addr(hdr->addr1))
+ return RX_DROP_UNUSABLE;
+
+ return __ieee80211_rx_h_amsdu(rx, 0);
+}
+
#ifdef CPTCFG_MAC80211_MESH
static ieee80211_rx_result
ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
@@ -3889,7 +3903,8 @@ static bool ieee80211_invoke_fast_rx(str
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct sta_info *sta = rx->sta;
int orig_len = skb->len;
- int snap_offs = ieee80211_hdrlen(hdr->frame_control);
+ int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ int snap_offs = hdrlen;
struct {
u8 snap[sizeof(rfc1042_header)];
__be16 proto;
@@ -3920,10 +3935,6 @@ static bool ieee80211_invoke_fast_rx(str
(status->flag & FAST_RX_CRYPT_FLAGS) != FAST_RX_CRYPT_FLAGS)
return false;
- /* we don't deal with A-MSDU deaggregation here */
- if (status->rx_flags & IEEE80211_RX_AMSDU)
- return false;
-
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
return false;
@@ -3955,21 +3966,24 @@ static bool ieee80211_invoke_fast_rx(str
snap_offs += IEEE80211_CCMP_HDR_LEN;
}
- if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
- goto drop;
- payload = (void *)(skb->data + snap_offs);
+ if (!(status->rx_flags & IEEE80211_RX_AMSDU)) {
+ if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
+ goto drop;
- if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr))
- return false;
+ payload = (void *)(skb->data + snap_offs);
- /* Don't handle these here since they require special code.
- * Accept AARP and IPX even though they should come with a
- * bridge-tunnel header - but if we get them this way then
- * there's little point in discarding them.
- */
- if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) ||
- payload->proto == fast_rx->control_port_protocol))
- return false;
+ if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr))
+ return false;
+
+ /* Don't handle these here since they require special code.
+ * Accept AARP and IPX even though they should come with a
+ * bridge-tunnel header - but if we get them this way then
+ * there's little point in discarding them.
+ */
+ if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) ||
+ payload->proto == fast_rx->control_port_protocol))
+ return false;
+ }
/* after this point, don't punt to the slowpath! */
@@ -3983,12 +3997,6 @@ static bool ieee80211_invoke_fast_rx(str
}
/* statistics part of ieee80211_rx_h_sta_process() */
- stats->last_rx = jiffies;
- stats->last_rate = sta_stats_encode_rate(status);
-
- stats->fragments++;
- stats->packets++;
-
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal;
if (!fast_rx->uses_rss)
@@ -4017,6 +4025,20 @@ static bool ieee80211_invoke_fast_rx(str
if (rx->key && !ieee80211_has_protected(hdr->frame_control))
goto drop;
+ if (status->rx_flags & IEEE80211_RX_AMSDU) {
+ if (__ieee80211_rx_h_amsdu(rx, snap_offs - hdrlen) !=
+ RX_QUEUED)
+ goto drop;
+
+ return true;
+ }
+
+ stats->last_rx = jiffies;
+ stats->last_rate = sta_stats_encode_rate(status);
+
+ stats->fragments++;
+ stats->packets++;
+
/* do the header conversion - first grab the addresses */
ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs);
ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs);
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4331,10 +4331,12 @@ unsigned int ieee80211_get_mesh_hdrlen(s
* of it being pushed into the SKB
* @addr: the device MAC address
* @iftype: the virtual interface type
+ * @data_offset: offset of payload after the 802.11 header
* Return: 0 on success. Non-zero on error.
*/
int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
- const u8 *addr, enum nl80211_iftype iftype);
+ const u8 *addr, enum nl80211_iftype iftype,
+ u8 data_offset);
/**
* ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
@@ -4346,7 +4348,7 @@ int ieee80211_data_to_8023_exthdr(struct
static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
enum nl80211_iftype iftype)
{
- return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype);
+ return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0);
}
/**
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -419,7 +419,8 @@ unsigned int ieee80211_get_mesh_hdrlen(s
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
- const u8 *addr, enum nl80211_iftype iftype)
+ const u8 *addr, enum nl80211_iftype iftype,
+ u8 data_offset)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct {
@@ -433,7 +434,7 @@ int ieee80211_data_to_8023_exthdr(struct
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
return -1;
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ hdrlen = ieee80211_hdrlen(hdr->frame_control) + data_offset;
if (skb->len < hdrlen + 8)
return -1;

View file

@ -0,0 +1,68 @@
From 5242a5444e0b6464d7455beb55d936dd192b5e9d Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Mon, 22 Jan 2018 21:46:39 +0100
Subject: [PATCH] brcmfmac: assure bcdc dcmd api does not return value > 0
The protocol layer api defines callbacks for dongle commands.
Although not really well documented these should only return an
error code in case of an error, or 0 upon success. In the bcdc
protocol it can return value above 0 and we carry a fix in the
caller of the protocol layer api. This patch makes it adhere to
the intent of the api as described above.
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 6 +++++-
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 8 +++-----
2 files changed, 8 insertions(+), 6 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
@@ -211,6 +211,8 @@ retry:
memcpy(buf, info, len);
}
+ ret = 0;
+
/* Check the ERROR flag */
if (flags & BCDC_DCMD_ERROR)
ret = le32_to_cpu(msg->status);
@@ -225,7 +227,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
{
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
- int ret = 0;
+ int ret;
u32 flags, id;
brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
@@ -249,6 +251,8 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
goto done;
}
+ ret = 0;
+
/* Check the ERROR flag */
if (flags & BCDC_DCMD_ERROR)
ret = le32_to_cpu(msg->status);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
@@ -121,11 +121,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
else
err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
- if (err >= 0)
- return 0;
-
- brcmf_dbg(FIL, "Failed: %s (%d)\n",
- brcmf_fil_get_errstr((u32)(-err)), err);
+ if (err)
+ brcmf_dbg(FIL, "Failed: %s (%d)\n",
+ brcmf_fil_get_errstr((u32)(-err)), err);
return err;
}

View file

@ -0,0 +1,186 @@
From b69c1df47281ad47bd2037a42b98f5c7115b7fd5 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Mon, 22 Jan 2018 21:46:40 +0100
Subject: [PATCH] brcmfmac: separate firmware errors from i/o errors
When using the firmware api it can fail simply because firmware does
not like the request or it fails due to issues in the host interface.
Currently, there is only a single error code which is confusing. So
adding a parameter to pass the firmware error separately and in case
of a firmware error always return -EBADE to user-space.
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 ++++++-----
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 16 +++++++++++-----
.../net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 10 ++++++----
drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h | 14 ++++++++------
4 files changed, 31 insertions(+), 20 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
@@ -165,7 +165,7 @@ static int brcmf_proto_bcdc_cmplt(struct
static int
brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len)
+ void *buf, uint len, int *fwerr)
{
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
@@ -175,6 +175,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf
brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+ *fwerr = 0;
ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
if (ret < 0) {
brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
@@ -215,15 +216,14 @@ retry:
/* Check the ERROR flag */
if (flags & BCDC_DCMD_ERROR)
- ret = le32_to_cpu(msg->status);
-
+ *fwerr = le32_to_cpu(msg->status);
done:
return ret;
}
static int
brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len)
+ void *buf, uint len, int *fwerr)
{
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
@@ -232,6 +232,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+ *fwerr = 0;
ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true);
if (ret < 0)
goto done;
@@ -255,7 +256,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
/* Check the ERROR flag */
if (flags & BCDC_DCMD_ERROR)
- ret = le32_to_cpu(msg->status);
+ *fwerr = le32_to_cpu(msg->status);
done:
return ret;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
@@ -107,7 +107,7 @@ static s32
brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
{
struct brcmf_pub *drvr = ifp->drvr;
- s32 err;
+ s32 err, fwerr;
if (drvr->bus_if->state != BRCMF_BUS_UP) {
brcmf_err("bus is down. we have nothing to do.\n");
@@ -117,14 +117,20 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
if (data != NULL)
len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
if (set)
- err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len);
+ err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd,
+ data, len, &fwerr);
else
- err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
+ err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd,
+ data, len, &fwerr);
- if (err)
+ if (err) {
brcmf_dbg(FIL, "Failed: %s (%d)\n",
brcmf_fil_get_errstr((u32)(-err)), err);
-
+ } else if (fwerr < 0) {
+ brcmf_dbg(FIL, "Firmware error: %s (%d)\n",
+ brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
+ err = -EBADE;
+ }
return err;
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -477,7 +477,7 @@ static void brcmf_msgbuf_ioctl_resp_wake
static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
- uint cmd, void *buf, uint len)
+ uint cmd, void *buf, uint len, int *fwerr)
{
struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
struct sk_buff *skb = NULL;
@@ -485,6 +485,7 @@ static int brcmf_msgbuf_query_dcmd(struc
int err;
brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len);
+ *fwerr = 0;
msgbuf->ctl_completed = false;
err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len);
if (err)
@@ -508,14 +509,15 @@ static int brcmf_msgbuf_query_dcmd(struc
}
brcmu_pkt_buf_free_skb(skb);
- return msgbuf->ioctl_resp_status;
+ *fwerr = msgbuf->ioctl_resp_status;
+ return 0;
}
static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx,
- uint cmd, void *buf, uint len)
+ uint cmd, void *buf, uint len, int *fwerr)
{
- return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len);
+ return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
@@ -30,9 +30,9 @@ struct brcmf_proto {
int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
struct sk_buff *skb, struct brcmf_if **ifp);
int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len);
+ void *buf, uint len, int *fwerr);
int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
- uint len);
+ uint len, int *fwerr);
int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx,
struct sk_buff *skb);
int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
@@ -71,14 +71,16 @@ static inline int brcmf_proto_hdrpull(st
return drvr->proto->hdrpull(drvr, do_fws, skb, ifp);
}
static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
- uint cmd, void *buf, uint len)
+ uint cmd, void *buf, uint len,
+ int *fwerr)
{
- return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len);
+ return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len,fwerr);
}
static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
- uint cmd, void *buf, uint len)
+ uint cmd, void *buf, uint len,
+ int *fwerr)
{
- return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
+ return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
}
static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx,

View file

@ -0,0 +1,92 @@
From 933897342d0714ae1c10729cbaeecea0c6178db5 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Wed, 28 Feb 2018 21:15:19 +0100
Subject: [PATCH] brcmfmac: add possibility to obtain firmware error
The feature module needs to evaluate the actual firmware error return
upon a control command. This adds a flag to struct brcmf_if that the
caller can set. This flag is checked to determine the error code that
needs to be returned.
Fixes: b69c1df47281 ("brcmfmac: separate firmware errors from i/o errors")
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h | 2 ++
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 10 ++++++++++
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 3 +++
3 files changed, 15 insertions(+)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -181,6 +181,7 @@ enum brcmf_netif_stop_reason {
* @netif_stop_lock: spinlock for update netif_stop from multiple sources.
* @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
* @pend_8021x_wait: used for signalling change in count.
+ * @fwil_fwerr: flag indicating fwil layer should return firmware error codes.
*/
struct brcmf_if {
struct brcmf_pub *drvr;
@@ -198,6 +199,7 @@ struct brcmf_if {
wait_queue_head_t pend_8021x_wait;
struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES];
u8 ipv6addr_idx;
+ bool fwil_fwerr;
};
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -104,6 +104,9 @@ static void brcmf_feat_iovar_int_get(str
u32 data;
int err;
+ /* we need to know firmware error */
+ ifp->fwil_fwerr = true;
+
err = brcmf_fil_iovar_int_get(ifp, name, &data);
if (err == 0) {
brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
@@ -112,6 +115,8 @@ static void brcmf_feat_iovar_int_get(str
brcmf_dbg(TRACE, "%s feature check failed: %d\n",
brcmf_feat_names[id], err);
}
+
+ ifp->fwil_fwerr = false;
}
static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
@@ -120,6 +125,9 @@ static void brcmf_feat_iovar_data_set(st
{
int err;
+ /* we need to know firmware error */
+ ifp->fwil_fwerr = true;
+
err = brcmf_fil_iovar_data_set(ifp, name, data, len);
if (err != -BRCMF_FW_UNSUPPORTED) {
brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
@@ -128,6 +136,8 @@ static void brcmf_feat_iovar_data_set(st
brcmf_dbg(TRACE, "%s feature check failed: %d\n",
brcmf_feat_names[id], err);
}
+
+ ifp->fwil_fwerr = false;
}
#define MAX_CAPS_BUFFER_SIZE 512
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
@@ -131,6 +131,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
err = -EBADE;
}
+ if (ifp->fwil_fwerr)
+ return fwerr;
+
return err;
}

View file

@ -0,0 +1,64 @@
From 455f3e76cfc0d893585a5f358b9ddbe9c1e1e53b Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Wed, 28 Feb 2018 21:15:20 +0100
Subject: [PATCH] brcmfmac: fix P2P_DEVICE ethernet address generation
The firmware has a requirement that the P2P_DEVICE address should
be different from the address of the primary interface. When not
specified by user-space, the driver generates the MAC address for
the P2P_DEVICE interface using the MAC address of the primary
interface and setting the locally administered bit. However, the MAC
address of the primary interface may already have that bit set causing
the creation of the P2P_DEVICE interface to fail with -EBUSY. Fix this
by using a random address instead to determine the P2P_DEVICE address.
Cc: stable@vger.kernel.org # 3.10.y
Reported-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 24 ++++++++++------------
1 file changed, 11 insertions(+), 13 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -462,25 +462,23 @@ static int brcmf_p2p_set_firmware(struct
* @dev_addr: optional device address.
*
* P2P needs mac addresses for P2P device and interface. If no device
- * address it specified, these are derived from the primary net device, ie.
- * the permanent ethernet address of the device.
+ * address it specified, these are derived from a random ethernet
+ * address.
*/
static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
{
- struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
- bool local_admin = false;
+ bool random_addr = false;
- if (!dev_addr || is_zero_ether_addr(dev_addr)) {
- dev_addr = pri_ifp->mac_addr;
- local_admin = true;
- }
+ if (!dev_addr || is_zero_ether_addr(dev_addr))
+ random_addr = true;
- /* Generate the P2P Device Address. This consists of the device's
- * primary MAC address with the locally administered bit set.
+ /* Generate the P2P Device Address obtaining a random ethernet
+ * address with the locally administered bit set.
*/
- memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
- if (local_admin)
- p2p->dev_addr[0] |= 0x02;
+ if (random_addr)
+ eth_random_addr(p2p->dev_addr);
+ else
+ memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
/* Generate the P2P Interface Address. If the discovery and connection
* BSSCFGs need to simultaneously co-exist, then this address must be

View file

@ -0,0 +1,157 @@
From 1259055170287a350cad453e9eac139c81609860 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Thu, 15 Mar 2018 08:29:09 +0100
Subject: [PATCH] brcmfmac: drop Inter-Access Point Protocol packets by default
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Testing brcmfmac with more recent firmwares resulted in AP interfaces
not working in some specific setups. Debugging resulted in discovering
support for IAPP in Broadcom's firmwares.
Older firmwares were only generating 802.11f frames. Newer ones like:
1) 10.10 (TOB) (r663589)
2) 10.10.122.20 (r683106)
for 4366b1 and 4366c0 respectively seem to also /respect/ 802.11f frames
in the Tx path by performing a STA disassociation.
This obsoleted standard and its implementation is something that:
1) Most people don't need / want to use
2) Can allow local DoS attacks
3) Breaks AP interfaces in some specific bridge setups
To solve issues it can cause this commit modifies brcmfmac to drop IAPP
packets. If affects:
1) Rx path: driver won't be sending these unwanted packets up.
2) Tx path: driver will reject packets that would trigger STA
disassociation perfromed by a firmware (possible local DoS attack).
It appears there are some Broadcom's clients/users who care about this
feature despite the drawbacks. They can switch it on using a new module
param.
This change results in only two more comparisons (check for module param
and check for Ethernet packet length) for 99.9% of packets. Its overhead
should be very minimal.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
.../wireless/broadcom/brcm80211/brcmfmac/common.c | 5 ++
.../wireless/broadcom/brcm80211/brcmfmac/common.h | 1 +
.../wireless/broadcom/brcm80211/brcmfmac/core.c | 57 ++++++++++++++++++++++
3 files changed, 63 insertions(+)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -75,6 +75,10 @@ static int brcmf_roamoff;
module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
+static int brcmf_iapp_enable;
+module_param_named(iapp, brcmf_iapp_enable, int, 0);
+MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol");
+
#ifdef DEBUG
/* always succeed brcmf_bus_started() */
static int brcmf_ignore_probe_fail;
@@ -441,6 +445,7 @@ struct brcmf_mp_device *brcmf_get_module
settings->feature_disable = brcmf_feature_disable;
settings->fcmode = brcmf_fcmode;
settings->roamoff = !!brcmf_roamoff;
+ settings->iapp = !!brcmf_iapp_enable;
#ifdef DEBUG
settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
#endif
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -58,6 +58,7 @@ struct brcmf_mp_device {
unsigned int feature_disable;
int fcmode;
bool roamoff;
+ bool iapp;
bool ignore_probe_fail;
struct brcmfmac_pd_cc *country_codes;
union {
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -230,6 +230,37 @@ static void brcmf_netdev_set_multicast_l
schedule_work(&ifp->multicast_work);
}
+/**
+ * brcmf_skb_is_iapp - checks if skb is an IAPP packet
+ *
+ * @skb: skb to check
+ */
+static bool brcmf_skb_is_iapp(struct sk_buff *skb)
+{
+ static const u8 iapp_l2_update_packet[6] __aligned(2) = {
+ 0x00, 0x01, 0xaf, 0x81, 0x01, 0x00,
+ };
+ unsigned char *eth_data;
+#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ const u16 *a, *b;
+#endif
+
+ if (skb->len - skb->mac_len != 6 ||
+ !is_multicast_ether_addr(eth_hdr(skb)->h_dest))
+ return false;
+
+ eth_data = skb_mac_header(skb) + ETH_HLEN;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ return !(((*(const u32 *)eth_data) ^ (*(const u32 *)iapp_l2_update_packet)) |
+ ((*(const u16 *)(eth_data + 4)) ^ (*(const u16 *)(iapp_l2_update_packet + 4))));
+#else
+ a = (const u16 *)eth_data;
+ b = (const u16 *)iapp_l2_update_packet;
+
+ return !((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]));
+#endif
+}
+
static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
struct net_device *ndev)
{
@@ -250,6 +281,23 @@ static netdev_tx_t brcmf_netdev_start_xm
goto done;
}
+ /* Some recent Broadcom's firmwares disassociate STA when they receive
+ * an 802.11f ADD frame. This behavior can lead to a local DoS security
+ * issue. Attacker may trigger disassociation of any STA by sending a
+ * proper Ethernet frame to the wireless interface.
+ *
+ * Moreover this feature may break AP interfaces in some specific
+ * setups. This applies e.g. to the bridge with hairpin mode enabled and
+ * IFLA_BRPORT_MCAST_TO_UCAST set. IAPP packet generated by a firmware
+ * will get passed back to the wireless interface and cause immediate
+ * disassociation of a just-connected STA.
+ */
+ if (!drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
+ dev_kfree_skb(skb);
+ ret = -EINVAL;
+ goto done;
+ }
+
/* Make sure there's enough writeable headroom */
if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) {
head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0);
@@ -325,6 +373,15 @@ void brcmf_txflowblock_if(struct brcmf_i
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
{
+ /* Most of Broadcom's firmwares send 802.11f ADD frame every time a new
+ * STA connects to the AP interface. This is an obsoleted standard most
+ * users don't use, so don't pass these frames up unless requested.
+ */
+ if (!ifp->drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
+ brcmu_pkt_buf_free_skb(skb);
+ return;
+ }
+
if (skb->pkt_type == PACKET_MULTICAST)
ifp->ndev->stats.multicast++;

View file

@ -0,0 +1,29 @@
From 9b9322db5c5a1917a66c71fe47c3848a9a31227e Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Wed, 14 Mar 2018 20:02:59 +0100
Subject: [PATCH] brcmfmac: Fix check for ISO3166 code
The commit "regulatory: add NUL to request alpha2" increases the length of
alpha2 to 3. This causes a regression on brcmfmac, because
brcmf_cfg80211_reg_notifier() expect valid ISO3166 codes in the complete
array. So fix this accordingly.
Fixes: 657308f73e67 ("regulatory: add NUL to request alpha2")
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
Acked-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -6803,7 +6803,7 @@ static void brcmf_cfg80211_reg_notifier(
return;
/* ignore non-ISO3166 country codes */
- for (i = 0; i < sizeof(req->alpha2); i++)
+ for (i = 0; i < 2; i++)
if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
req->alpha2[0], req->alpha2[1]);

View file

@ -0,0 +1,45 @@
From da472385a29f1fddcac7cfa0499482704310bd16 Mon Sep 17 00:00:00 2001
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
Date: Tue, 20 Feb 2018 00:14:18 +0100
Subject: [PATCH] brcmfmac: move brcmf_bus_preinit() call just after changing
bus state
Moving the brcmf_bus_preinit() call allows the bus code to do some
required initialization before handling firmware control messages.
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 3 ---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 5 +++++
2 files changed, 5 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -369,9 +369,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
/* Enable tx beamforming, errors can be ignored (not supported) */
(void)brcmf_fil_iovar_int_set(ifp, "txbf", 1);
-
- /* do bus specific preinit here */
- err = brcmf_bus_preinit(ifp->drvr->bus_if);
done:
return err;
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -1091,6 +1091,11 @@ int brcmf_bus_started(struct device *dev
/* signal bus ready */
brcmf_bus_change_state(bus_if, BRCMF_BUS_UP);
+ /* do bus specific preinit here */
+ ret = brcmf_bus_preinit(ifp->drvr->bus_if);
+ if (ret < 0)
+ goto fail;
+
/* Bus is ready, do any initialization */
ret = brcmf_c_preinit_dcmds(ifp);
if (ret < 0)

Some files were not shown because too many files have changed in this diff Show more