[RFC 0/4] wireless: Per-sta NoAck and offload support
Adds infrastructure for driver to offload NoAck functionality, driver like ath10k could make use of it. Also extends the current ndev wide NoAck policy to per-station, with sta level NoAck policy configuration userspace could selectively turn off/on Noack based on various connection parameters of the station. Vasanthakumar Thiagarajan (4): mac80211: Add NoAck policy functionality offload infrastructure nl80211/mac80211: Extend NoAck policy command with peer MAC address mac80211: Apply per-peer NoAck tid bitmap configuration mac80211: Advertise per-peer NoAck policy support include/net/cfg80211.h | 9 +++-- include/net/mac80211.h | 18 ++ include/uapi/linux/nl80211.h | 12 +++- net/mac80211/cfg.c | 45 +--- net/mac80211/debugfs.c | 1 + net/mac80211/driver-ops.h| 22 ++ net/mac80211/iface.c | 4 net/mac80211/main.c | 8 net/mac80211/sta_info.h | 3 +++ net/mac80211/trace.h | 28 +++ net/mac80211/tx.c| 3 ++- net/mac80211/wme.c | 35 +- net/wireless/nl80211.c | 12 +++- net/wireless/rdev-ops.h | 7 --- net/wireless/trace.h | 11 +++ 15 files changed, 202 insertions(+), 16 deletions(-) -- 1.9.1
[RFC 4/4] mac80211: Advertise per-peer NoAck policy support
This enables per-peer NoAck handling in mac80211 when the functionality is not offloaded to the drivers. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@codeaurora.org> --- net/mac80211/main.c | 4 1 file changed, 4 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 78f2574..2b136fb 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -565,6 +565,10 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM); + if (!ops->set_noack_tid_bitmap) + wiphy_ext_feature_set(wiphy, + NL80211_EXT_FEATURE_PER_STA_NOACK_MAP); + wiphy->bss_priv_size = sizeof(struct ieee80211_bss); local = wiphy_priv(wiphy); -- 1.9.1
[RFC 2/4] nl80211/mac80211: Extend NoAck policy command with peer MAC address
Provides peer level NoAck policy configuration by extending NL80211_CMD_SET_NOACK_MAP command with peer MAC address. If user space does not give any peer mac address, the driver should retain the existing functionality of applying the NoAck policy for all the staions connected to the netdev. Peer specific configuration takes precedence over netdev level configuration when both are set by the user. Drivers supporting per-sta NoAck policy must advertise the support through the extended flag index NL80211_EXT_FEATURE_PER_STA_NOACK_MAP. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@codeaurora.org> --- include/net/cfg80211.h | 9 +++-- include/uapi/linux/nl80211.h | 12 +++- net/mac80211/cfg.c | 1 + net/wireless/nl80211.c | 12 +++- net/wireless/rdev-ops.h | 7 --- net/wireless/trace.h | 11 +++ 6 files changed, 41 insertions(+), 11 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index fc40843..b974d32 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2872,7 +2872,12 @@ struct cfg80211_external_auth_params { * @probe_client: probe an associated client, must return a cookie that it * later passes to cfg80211_probe_status(). * - * @set_noack_map: Set the NoAck Map for the TIDs. + * @set_noack_map: Set the NoAck Map for the TIDs. When peer is not %NULL NoAck + * map will be applied for that particular peer. When peer is %NULL NoAck + * map will be applied for all the connected stations (except the ones + * which already have per-peer TID map configured) on the netdev. + * Driver should return -ENOSPC when the it does not have room for + * additional entries for per-peer NoAck map. * * @get_channel: Get the current operating channel for the virtual interface. * For monitor interfaces, it should return %NULL unless there's a single @@ -3180,7 +3185,7 @@ struct cfg80211_ops { int (*set_noack_map)(struct wiphy *wiphy, struct net_device *dev, - u16 noack_map); + const u8 *peer, u16 noack_map); int (*get_channel)(struct wiphy *wiphy, struct wireless_dev *wdev, diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 60fefc5..7425ea6 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -784,7 +784,14 @@ * messages. Note that per PHY only one application may register. * * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether - * No Acknowledgement Policy should be applied. + * No Acknowledgement Policy should be applied. %NL80211_ATTR_MAC is used + * to apply No Acknowledgement policy for a particular connected station. + * Station specific NoAck policy configuration is valid only for STA's + * current connection, i.e. the configuration will not be used when the + * station connects back after disconnection/roaming. + * When user-space does not include %NL80211_ATTR_MAC, the No + * Acknowledgement Policy setting should be treated as per-netdev + * configuration. * * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels * independently of the userspace SME, send this event indicating @@ -5005,6 +5012,8 @@ enum nl80211_feature_flags { * channel change triggered by radar detection event. * No need to start CAC from user-space, no need to react to * "radar detected" event. + * @NL80211_EXT_FEATURE_PER_STA_NOACK_MAP: Driver supports STA specific NoAck + * policy functionality. * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. @@ -5036,6 +5045,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_LOW_POWER_SCAN, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN, NL80211_EXT_FEATURE_DFS_OFFLOAD, + NL80211_EXT_FEATURE_PER_STA_NOACK_MAP, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a2f0eae..621ef38 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -341,6 +341,7 @@ static void ieee80211_del_nan_func(struct wiphy *wiphy, static int ieee80211_set_noack_map(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u16 noack_map) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fe27ab4..8d7f055a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3095,16 +3095,26 @@ static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info) struct cfg80211_registered_device *rdev =
[RFC 1/4] mac80211: Add NoAck policy functionality offload infrastructure
Add infrastructure for drivers to implement NoAck policy functionlity. Driver like ath10k does not use the per-packet TID NoAck policy configuration. Instead NoAck map is sent to the firmware/hardware in control path. Firmware takes care of setting up QOS header and hw with NoAck policy based on the TID NoAck map. Drivers having this support should advertise it through a new hw_flag, IEEE80211_HW_SUPPORTS_NOACK_POLICY, and must implement callback set_noack_tid_bitmap(). Supporting drivers would receive TID NoAck map through set_noack_tid_bitmap() instead of receiving as part of every tx skb. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@codeaurora.org> --- include/net/mac80211.h| 15 +++ net/mac80211/cfg.c| 10 -- net/mac80211/debugfs.c| 1 + net/mac80211/driver-ops.h | 21 + net/mac80211/iface.c | 4 net/mac80211/main.c | 4 net/mac80211/trace.h | 25 + net/mac80211/tx.c | 3 ++- net/mac80211/wme.c| 3 ++- 9 files changed, 82 insertions(+), 4 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d39fd68..5a49c90 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2081,6 +2081,13 @@ struct ieee80211_txq { * the frame, as it is not synced with the AP/P2P GO yet, and thus the * deauthentication frame might not be transmitted. * + * @IEEE80211_HW_SUPPORTS_NOACK_POLICY: Hardware (or driver) manages noack + * policy handling. Hardware (or driver) takes care of setting + * noack policy in the qos header and does not wait for the ack based + * on the noack TID map. Driver advertising this support must implement + * callback @set_noack_tid_bitmap to receive the user configured noack TID + * bitmap. + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2125,6 +2132,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_TX_FRAG, IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA, IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP, + IEEE80211_HW_SUPPORTS_NOACK_POLICY, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS @@ -3490,6 +3498,10 @@ enum ieee80211_reconfig_type { * @del_nan_func: Remove a NAN function. The driver must call * ieee80211_nan_func_terminated() with * NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST reason code upon removal. + * + * @set_noack_tid_bitmap: Set NoAck policy TID bitmap for a virtual interface. + * Drivers advertising NoAck policy handing support + * (%IEEE80211_HW_SUPPORTS_NOACK_POLICY) must implement this callback. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, @@ -3771,6 +3783,9 @@ struct ieee80211_ops { void (*del_nan_func)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 instance_id); + + int (*set_noack_tid_bitmap)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 noack_map); }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5c4b105..a2f0eae 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -347,9 +347,15 @@ static int ieee80211_set_noack_map(struct wiphy *wiphy, sdata->noack_map = noack_map; - ieee80211_check_fast_xmit_iface(sdata); + if (!ieee80211_hw_check(>local->hw, SUPPORTS_NOACK_POLICY)) { + ieee80211_check_fast_xmit_iface(sdata); + return 0; + } - return 0; + if (!ieee80211_sdata_running(sdata)) + return 0; + + return drv_set_noack_tid_bitmap(sdata->local, sdata, noack_map); } static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index a75653a..b6e6243 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -213,6 +213,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf, FLAG(SUPPORTS_TX_FRAG), FLAG(SUPPORTS_TDLS_BUFFER_STA), FLAG(DEAUTH_NEED_MGD_TX_PREP), + FLAG(SUPPORTS_NOACK_POLICY), #undef FLAG }; diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 4d82fe7..a0a2d3c 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -1250,4 +1250,25 @@ static inline void drv_del_nan_func(struct ieee80211_local *local, trace_drv_return_void(local); } +static inline int drv_set_noack_tid_bitmap(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + u16 noack_map) +{ + int ret; + + might_sleep(); + if (!check_sdata_in_driver(sdata)) + return -EIO; + + if (!local->ops->set_noack_tid_bitmap) + return -EOPNOTSUPP; + + trace_drv_se
[RFC 3/4] mac80211: Apply per-peer NoAck tid bitmap configuration
Use per-peer noack tid bitmap, if it is configured, when setting up the qos header. If no per-peer configuration is set, use the existing nedev wide noack policy configuration. Also modifies callback set_noack_tid_bitmap() with the provision to send per-peer NoAck policy configuration to the drivers supporting the NoAck offload functionality (IEEE80211_HW_SUPPORTS_NOACK_POLICY). Signed-off-by: Vasanthakumar Thiagarajan <vthia...@codeaurora.org> --- include/net/mac80211.h| 7 +-- net/mac80211/cfg.c| 42 +- net/mac80211/driver-ops.h | 5 +++-- net/mac80211/iface.c | 2 +- net/mac80211/sta_info.h | 3 +++ net/mac80211/trace.h | 9 ++--- net/mac80211/tx.c | 2 +- net/mac80211/wme.c| 34 +- 8 files changed, 89 insertions(+), 15 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5a49c90..a5ed552 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3499,7 +3499,9 @@ enum ieee80211_reconfig_type { * ieee80211_nan_func_terminated() with * NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST reason code upon removal. * - * @set_noack_tid_bitmap: Set NoAck policy TID bitmap for a virtual interface. + * @set_noack_tid_bitmap: Set NoAck policy TID bitmap. Apply the TID NoAck + * configuration for a particular station when @sta is non-NULL. When @sta + * is NULL, apply TID NoAck configuration at virtual interface level. * Drivers advertising NoAck policy handing support * (%IEEE80211_HW_SUPPORTS_NOACK_POLICY) must implement this callback. */ @@ -3785,7 +3787,8 @@ struct ieee80211_ops { u8 instance_id); int (*set_noack_tid_bitmap)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u8 noack_map); + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u8 noack_map); }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 621ef38..1efc9cf 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -345,18 +345,50 @@ static int ieee80211_set_noack_map(struct wiphy *wiphy, u16 noack_map) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct sta_info *sta; + int ret; - sdata->noack_map = noack_map; + if (!peer) { + sdata->noack_map = noack_map; - if (!ieee80211_hw_check(>local->hw, SUPPORTS_NOACK_POLICY)) { - ieee80211_check_fast_xmit_iface(sdata); - return 0; + if (!ieee80211_hw_check(>local->hw, SUPPORTS_NOACK_POLICY)) { + ieee80211_check_fast_xmit_iface(sdata); + return 0; + } + + if (!ieee80211_sdata_running(sdata)) + return 0; + + return drv_set_noack_tid_bitmap(sdata->local, sdata, NULL, + noack_map); } + /* NoAck policy is for a connected client on the dev */ + if (!ieee80211_sdata_running(sdata)) + return -ENETDOWN; + + mutex_lock(>local->sta_mtx); + + sta = sta_info_get_bss(sdata, peer); + if (!sta) { + mutex_unlock(>local->sta_mtx); + return -ENOENT; + } + + sta->noack_map = noack_map; + + if (!ieee80211_hw_check(>local->hw, SUPPORTS_NOACK_POLICY)) { + ieee80211_check_fast_xmit(sta); + mutex_unlock(>local->sta_mtx); return 0; + } + + ret = drv_set_noack_tid_bitmap(sdata->local, sdata, sta, noack_map); - return drv_set_noack_tid_bitmap(sdata->local, sdata, noack_map); + mutex_unlock(>local->sta_mtx); + + return ret; } static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index a0a2d3c..8a2154a 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -1252,6 +1252,7 @@ static inline void drv_del_nan_func(struct ieee80211_local *local, static inline int drv_set_noack_tid_bitmap(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, u16 noack_map) { int ret; @@ -1263,9 +1264,9 @@ static inline int drv_set_noack_tid_bitmap(struct ieee80211_local *local, if (!local->ops->set_noack_tid_bitmap) return -EOPNOTSUPP; - trace_drv_set_noack_tid_bitmap(local, sdata, noack_map); + trace_drv_set_noack_tid_bitmap(local, sdata, >sta, noack_map); ret = local->ops->set_noa
Re: [PATCH] ath10k: Add sta rx packet stats per tid
On Wednesday 28 February 2018 06:47 PM, Kalle Valo wrote: > Vasanthakumar Thiagarajan <vthia...@codeaurora.org> writes: > >> Added per tid sta counters for the following >> >> - Total number MSDUs received from firmware >> - Number of MSDUs received with errors like decryption, crc, mic ,etc. >> - Number of MSDUs dropped in the driver >> - A-MPDU/A-MSDU subframe stats >> - Number of MSDUS passed to mac80211 >> >> All stats other than A-MPDU stats are only for received data frames. >> A-MPDU stats might have stats for management frames when monitor >> interface is active where management frames are notified both in wmi >> and HTT interfaces. >> >> These per tid stats can be enabled with tid bitmask through a debugfs >> like below >> >> echo > >> /sys/kernel/debug/ieee80211/phyX/ath10k/sta_tid_stats_mask >> >> tid 16 (tid_bitmask 0x1) is used for non-qos data/management frames >> >> The stats are read from >> /sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations//dump_tid_stats >> >> Sample output: >> >> To enable rx stats for tid 0, 5 and 6, >> >> echo 0x0061 > >> /sys/kernel/debug/ieee80211/phy0/ath10k/sta_tid_stats_mask >> >> cat >> /sys/kernel/debug/ieee80211/phy0/netdev\:wlan15/stations/8c\:fd\:f0\:0a\:8e\:df/dump_tid_stats >> >> Driver Rx pkt stats per tid, ([tid] count) >> -- >> MSDUs from FW [00] 2567[05] 3178[06] 1089 >> MSDUs unchained [00] 0 [05] 0 [06] 0 >> MSDUs locally dropped:chained [00] 0 [05] 0 [06] 0 >> MSDUs locally dropped:filtered [00] 0 [05] 0 [06] 0 >> MSDUs queued for mac80211 [00] 2567[05] 3178[06] 1089 >> MSDUs with error:fcs_err[00] 0 [05] 0 [06] 2 >> MSDUs with error:tkip_err [00] 0 [05] 0 [06] 0 >> MSDUs with error:crypt_err [00] 0 [05] 0 [06] 0 >> MSDUs with error:peer_idx_inval [00] 0 [05] 0 [06] 0 >> >> A-MPDU num subframes upto 10[00] 2567[05] 3178[06] 1087 >> A-MPDU num subframes 11-20 [00] 0 [05] 0 [06] 0 >> A-MPDU num subframes 21-30 [00] 0 [05] 0 [06] 0 >> A-MPDU num subframes 31-40 [00] 0 [05] 0 [06] 0 >> A-MPDU num subframes 41-50 [00] 0 [05] 0 [06] 0 >> A-MPDU num subframes 51-60 [00] 0 [05] 0 [06] 0 >> A-MPDU num subframes >60[00] 0 [05] 0 [06] 0 >> >> A-MSDU num subframes 1 [00] 2567[05] 3178 [06] 1089 >> A-MSDU num subframes 2 [00] 0 [05] 0 [06] 0 >> A-MSDU num subframes 3 [00] 0 [05] 0 [06] 0 >> A-MSDU num subframes 4 [00] 0 [05] 0 [06] 0 >> A-MSDU num subframes >4 [00] 0 [05] 0 [06] 0 >> >> Signed-off-by: Vasanthakumar Thiagarajan <vthia...@codeaurora.org> > > This added new ath10k-check warnings, I fixed those in the pending > branch: > > drivers/net/wireless/ath/ath10k/debug.h:203: Alignment should match open > parenthesis > drivers/net/wireless/ath/ath10k/debug.h:226: Alignment should match open > parenthesis > drivers/net/wireless/ath/ath10k/debugfs_sta.c:24: Alignment should match open > parenthesis > drivers/net/wireless/ath/ath10k/debugfs_sta.c:40: Alignment should match open > parenthesis > drivers/net/wireless/ath/ath10k/debugfs_sta.c:60: Alignment should match open > parenthesis > > Also I fixed the typo "rages" in debug.h. My changes: Thanks for fixing it. In most of the cases, fixing above warnings would result in lines > 80 chars. May be we need not be very strict about > 80 char limit? Vasanth
[PATCH] ath10k: Add sta rx packet stats per tid
Added per tid sta counters for the following - Total number MSDUs received from firmware - Number of MSDUs received with errors like decryption, crc, mic ,etc. - Number of MSDUs dropped in the driver - A-MPDU/A-MSDU subframe stats - Number of MSDUS passed to mac80211 All stats other than A-MPDU stats are only for received data frames. A-MPDU stats might have stats for management frames when monitor interface is active where management frames are notified both in wmi and HTT interfaces. These per tid stats can be enabled with tid bitmask through a debugfs like below echo > /sys/kernel/debug/ieee80211/phyX/ath10k/sta_tid_stats_mask tid 16 (tid_bitmask 0x1) is used for non-qos data/management frames The stats are read from /sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations//dump_tid_stats Sample output: To enable rx stats for tid 0, 5 and 6, echo 0x0061 > /sys/kernel/debug/ieee80211/phy0/ath10k/sta_tid_stats_mask cat /sys/kernel/debug/ieee80211/phy0/netdev\:wlan15/stations/8c\:fd\:f0\:0a\:8e\:df/dump_tid_stats Driver Rx pkt stats per tid, ([tid] count) -- MSDUs from FW [00] 2567[05] 3178[06] 1089 MSDUs unchained [00] 0 [05] 0 [06] 0 MSDUs locally dropped:chained [00] 0 [05] 0 [06] 0 MSDUs locally dropped:filtered [00] 0 [05] 0 [06] 0 MSDUs queued for mac80211 [00] 2567[05] 3178[06] 1089 MSDUs with error:fcs_err[00] 0 [05] 0 [06] 2 MSDUs with error:tkip_err [00] 0 [05] 0 [06] 0 MSDUs with error:crypt_err [00] 0 [05] 0 [06] 0 MSDUs with error:peer_idx_inval [00] 0 [05] 0 [06] 0 A-MPDU num subframes upto 10[00] 2567[05] 3178[06] 1087 A-MPDU num subframes 11-20 [00] 0 [05] 0 [06] 0 A-MPDU num subframes 21-30 [00] 0 [05] 0 [06] 0 A-MPDU num subframes 31-40 [00] 0 [05] 0 [06] 0 A-MPDU num subframes 41-50 [00] 0 [05] 0 [06] 0 A-MPDU num subframes 51-60 [00] 0 [05] 0 [06] 0 A-MPDU num subframes >60[00] 0 [05] 0 [06] 0 A-MSDU num subframes 1 [00] 2567[05] 3178[06] 1089 A-MSDU num subframes 2 [00] 0 [05] 0 [06] 0 A-MSDU num subframes 3 [00] 0 [05] 0 [06] 0 A-MSDU num subframes 4 [00] 0 [05] 0 [06] 0 A-MSDU num subframes >4 [00] 0 [05] 0 [06] 0 Signed-off-by: Vasanthakumar Thiagarajan <vthia...@codeaurora.org> --- drivers/net/wireless/ath/ath10k/core.h| 45 drivers/net/wireless/ath/ath10k/debug.c | 48 + drivers/net/wireless/ath/ath10k/debug.h | 31 +++ drivers/net/wireless/ath/ath10k/debugfs_sta.c | 286 ++ drivers/net/wireless/ath/ath10k/htt_rx.c | 71 ++- 5 files changed, 471 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index fe6b30356d3b..c624b96f8b84 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -354,6 +355,45 @@ struct ath10k_txq { unsigned long num_push_allowed; }; +enum ath10k_pkt_rx_err { + ATH10K_PKT_RX_ERR_FCS, + ATH10K_PKT_RX_ERR_TKIP, + ATH10K_PKT_RX_ERR_CRYPT, + ATH10K_PKT_RX_ERR_PEER_IDX_INVAL, + ATH10K_PKT_RX_ERR_MAX, +}; + +enum ath10k_ampdu_subfrm_num { + ATH10K_AMPDU_SUBFRM_NUM_10, + ATH10K_AMPDU_SUBFRM_NUM_20, + ATH10K_AMPDU_SUBFRM_NUM_30, + ATH10K_AMPDU_SUBFRM_NUM_40, + ATH10K_AMPDU_SUBFRM_NUM_50, + ATH10K_AMPDU_SUBFRM_NUM_60, + ATH10K_AMPDU_SUBFRM_NUM_MORE, + ATH10K_AMPDU_SUBFRM_NUM_MAX, +}; + +enum ath10k_amsdu_subfrm_num { + ATH10K_AMSDU_SUBFRM_NUM_1, + ATH10K_AMSDU_SUBFRM_NUM_2, + ATH10K_AMSDU_SUBFRM_NUM_3, + ATH10K_AMSDU_SUBFRM_NUM_4, + ATH10K_AMSDU_SUBFRM_NUM_MORE, + ATH10K_AMSDU_SUBFRM_NUM_MAX, +}; + +struct ath10k_sta_tid_stats { + unsigned long int rx_pkt_from_fw; + unsigned long int rx_pkt_unchained; + unsigned long int rx_pkt_drop_chained; + unsigned long int rx_pkt_drop_filter; + unsigned long int rx_pkt_err[ATH10K_PKT_RX_ERR_MAX]; + unsigned long int rx_pkt_queued_for_mac; + unsigned long int rx_pkt_ampdu[ATH10K_AM
Re: [v3] ath10k: rebuild crypto header in rx data frames
Sorry top posting. The issues in raw mode with CCMP-256, GCMP and GCMP-256 were already known and the same was captured in the commit log. As mentioned in the commit log, raw mode with these ciphers does not work even without this particular patch and it needs some cleanup like done in the follow up patch https://patchwork.kernel.org/patch/10029099/. Vasanth From: Sebastian Gottschall <s.gottsch...@dd-wrt.com> Sent: Tuesday, October 31, 2017 8:24 PM To: Kalle Valo Cc: ath...@lists.infradead.org; linux-wireless@vger.kernel.org; Vasanthakumar Thiagarajan Subject: Re: [v3] ath10k: rebuild crypto header in rx data frames the same is for the MIC + /* MIC */ + if ((status->flag & RX_FLAG_MIC_STRIPPED) && + enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) + skb_trim(msdu, msdu->len - 8); this code looks wrong too Am 30.10.2017 um 10:32 schrieb Sebastian Gottschall: > will check it tomorrow including gcmp-256, ccmp-256. was out for > weekend :-) > > Am 30.10.2017 um 09:39 schrieb Kalle Valo: >> Kalle Valo <kv...@qca.qualcomm.com> wrote: >> >>> Rx data frames notified through HTT_T2H_MSG_TYPE_RX_IND and >>> HTT_T2H_MSG_TYPE_RX_FRAG_IND expect PN/TSC check to be done >>> on host (mac80211) rather than firmware. Rebuild cipher header >>> in every received data frames (that are notified through those >>> HTT interfaces) from the rx_hdr_status tlv available in the >>> rx descriptor of the first msdu. Skip setting RX_FLAG_IV_STRIPPED >>> flag for the packets which requires mac80211 PN/TSC check support >>> and set appropriate RX_FLAG for stripped crypto tail. Hw QCA988X, >>> QCA9887, QCA99X0, QCA9984, QCA9888 and QCA4019 currently need the >>> rebuilding of cipher header to perform PN/TSC check for replay >>> attack. >>> >>> Please note that removing crypto tail for CCMP-256, GCMP and >>> GCMP-256 ciphers >>> in raw mode needs to be fixed. Since Rx with these ciphers in raw >>> mode does not work in the current form even without this patch and >>> removing crypto tail for these chipers needs clean up, raw mode related >>> issues in CCMP-256, GCMP and GCMP-256 can be addressed in follow up >>> patches. >>> >>> Tested-by: Manikanta Pubbisetty <mpubb...@qti.qualcomm.com> >>> Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> >>> Signed-off-by: Kalle Valo <kv...@qca.qualcomm.com> >> Patch applied to ath-current branch of ath.git, thanks. >> >> 7eccb738fce5 ath10k: rebuild crypto header in rx data frames >> > -- Mit freundlichen Grüssen / Regards Sebastian Gottschall / CTO NewMedia-NET GmbH - DD-WRT Firmensitz: Stubenwaldallee 21a, 64625 Bensheim Registergericht: Amtsgericht Darmstadt, HRB 25473 Geschäftsführer: Peter Steinhäuser, Christian Scheele http://www.dd-wrt.com email: s.gottsch...@dd-wrt.com Tel.: +496251-582650 / Fax: +496251-5826565
[PATCH] ath10k: Fix data rx for CCMP-256, GCMP and GCMP-256 in raw mode
Make sure 16-byte mic is removed from the rx data packet tail when CCMP-256, GCMP and GCMP-256 ciphers are used in raw decap mode. This fixed rx traffic failures in those ciphers in raw mode. Split the helper returning crypto tail length into two, one to get the ICV length and other to get the mic lengh for the cipher to make it clean. Fixes: 2ea9f12cefe4 ("ath10k: add new cipher suite support") Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- This patch depends on https://patchwork.kernel.org/patch/10028621/ drivers/net/wireless/ath/ath10k/htt_rx.c | 51 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 5beb6ee0f091..656385f80929 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -566,18 +566,16 @@ static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar, #define MICHAEL_MIC_LEN 8 -static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar, -enum htt_rx_mpdu_encrypt_type type) +static int ath10k_htt_rx_crypto_mic_len(struct ath10k *ar, + enum htt_rx_mpdu_encrypt_type type) { switch (type) { case HTT_RX_MPDU_ENCRYPT_NONE: - return 0; case HTT_RX_MPDU_ENCRYPT_WEP40: case HTT_RX_MPDU_ENCRYPT_WEP104: - return IEEE80211_WEP_ICV_LEN; case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: - return IEEE80211_TKIP_ICV_LEN; + return 0; case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: return IEEE80211_CCMP_MIC_LEN; case HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2: @@ -594,6 +592,31 @@ static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar, return 0; } +static int ath10k_htt_rx_crypto_icv_len(struct ath10k *ar, + enum htt_rx_mpdu_encrypt_type type) +{ + switch (type) { + case HTT_RX_MPDU_ENCRYPT_NONE: + case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: + case HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2: + case HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2: + case HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2: + return 0; + case HTT_RX_MPDU_ENCRYPT_WEP40: + case HTT_RX_MPDU_ENCRYPT_WEP104: + return IEEE80211_WEP_ICV_LEN; + case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: + case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: + return IEEE80211_TKIP_ICV_LEN; + case HTT_RX_MPDU_ENCRYPT_WEP128: + case HTT_RX_MPDU_ENCRYPT_WAPI: + break; + } + + ath10k_warn(ar, "unsupported encryption type %d\n", type); + return 0; +} + struct amsdu_subframe_hdr { u8 dst[ETH_ALEN]; u8 src[ETH_ALEN]; @@ -1063,25 +1086,27 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, /* Tail */ if (status->flag & RX_FLAG_IV_STRIPPED) { skb_trim(msdu, msdu->len - -ath10k_htt_rx_crypto_tail_len(ar, enctype)); +ath10k_htt_rx_crypto_mic_len(ar, enctype)); + + skb_trim(msdu, msdu->len - +ath10k_htt_rx_crypto_icv_len(ar, enctype)); } else { /* MIC */ - if ((status->flag & RX_FLAG_MIC_STRIPPED) && - enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) - skb_trim(msdu, msdu->len - 8); + if (status->flag & RX_FLAG_MIC_STRIPPED) + skb_trim(msdu, msdu->len - +ath10k_htt_rx_crypto_mic_len(ar, enctype)); /* ICV */ - if (status->flag & RX_FLAG_ICV_STRIPPED && - enctype != HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) + if (status->flag & RX_FLAG_ICV_STRIPPED) skb_trim(msdu, msdu->len - -ath10k_htt_rx_crypto_tail_len(ar, enctype)); +ath10k_htt_rx_crypto_icv_len(ar, enctype)); } /* MMIC */ if ((status->flag & RX_FLAG_MMIC_STRIPPED) && !ieee80211_has_morefrags(hdr->frame_control) && enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) - skb_trim(msdu, msdu->len - 8); + skb_trim(msdu, msdu->len - MICHAEL_MIC_LEN); /* Head */ if (status->flag & RX_FLAG_IV_STRIPPED) { -- 1.9.1
Re: [PATCH] ath10k: rebuild crypto header in RX data frames
On Saturday 21 October 2017 01:41 AM, Sebastian Gottschall wrote: > i suggest the following patch on top of yours. please tell me if my thoughts > are correct here. its mainly a guess I agree we need to take care of this for newly added ciphers as well. How about making it as a separate patch to make the patch bit smaller and to reduce the difficulties in back porting it for ciphers supported for long time? Vasanth
[PATCH] cfg80211: Fix dfs state propagation for non-DFS center channel
When part of a bigger bandwidth (160 MHz) channel falls in DFS channel range it is possible that the center frequency may not necessarily be a radar channel. Remove the sanity check on channel flag for IEEE80211_CHAN_RADAR in regulatory_propagate_dfs_state(), this should fix the dfs state propagation for non-DFS center freq which has DFS channels in it's bandwidth, should also fix unnecessary WARN_ON() spam in regulatory_propagate_dfs_state(). Fixes: 8976672736d6 ("cfg80211: Share Channel DFS state across wiphys of same DFS domain") Reported-by: Johannes Berg <johan...@sipsolutions.net> Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- net/wireless/reg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index a38f315..5fae296 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -3244,9 +3244,6 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy, if (WARN_ON(!cfg80211_chandef_valid(chandef))) return; - if (WARN_ON(!(chandef->chan->flags & IEEE80211_CHAN_RADAR))) - return; - list_for_each_entry(rdev, _rdev_list, list) { if (wiphy == >wiphy) continue; -- 1.9.1
Re: [PATCH V2 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain
On Tuesday 18 April 2017 04:20 PM, Johannes Berg wrote: > >> +void regulatory_propagate_dfs_state(struct wiphy *wiphy, >> +struct cfg80211_chan_def >> *chandef, >> +enum nl80211_dfs_state >> dfs_state, >> +enum nl80211_radar_event event) >> +{ >> +struct cfg80211_registered_device *rdev; >> + >> +ASSERT_RTNL(); >> + >> +if (WARN_ON(!cfg80211_chandef_valid(chandef))) >> +return; >> + >> +if (WARN_ON(!(chandef->chan->flags & IEEE80211_CHAN_RADAR))) >> +return; > > > This warn on reliably triggers for me when I run the "ap_vht160" hwsim > test from wpa_supplicant. > > I think there might be some confusion about this when parts of the 160 > MHz channel require radar and parts don't? But I haven't looked into > this at all. Correct, when some part of a bigger bandwidth channel falls in DFS channel range channel definition of that channel's center freq is may not be a radar channel and bailing out based on the channel flag there is not right. Sorry for the bug and thanks for reporting it. > > Please send me a fix ASAP so Jouni doesn't shout at me for test > failures :) Sure. Vasanth
[PATCH V2 2/3] cfg80211: Disallow moving out of operating DFS channel in non-ETSI
For non-ETSI regulatory domain, CAC result on DFS channel may not be valid once moving out of that channel (as done during remain-on-channel, scannning and off-channel tx). Running CAC on an operating DFS channel after every off-channel operation will only add complexity and disturb the current link. Better do not allow any off-channel switch from a DFS operating channel in non-ETSI domain. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- net/wireless/nl80211.c | 52 ++ 1 file changed, 52 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d516527..b15903b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6556,6 +6556,19 @@ static int nl80211_parse_random_mac(struct nlattr **attrs, return 0; } +static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev) +{ + ASSERT_WDEV_LOCK(wdev); + + if (!cfg80211_beaconing_iface_active(wdev)) + return true; + + if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR)) + return true; + + return regulatory_pre_cac_allowed(wdev->wiphy); +} + static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -6681,6 +6694,25 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) request->n_channels = i; + wdev_lock(wdev); + if (!cfg80211_off_channel_oper_allowed(wdev)) { + struct ieee80211_channel *chan; + + if (request->n_channels != 1) { + wdev_unlock(wdev); + err = -EBUSY; + goto out_free; + } + + chan = request->channels[0]; + if (chan->center_freq != wdev->chandef.chan->center_freq) { + wdev_unlock(wdev); + err = -EBUSY; + goto out_free; + } + } + wdev_unlock(wdev); + i = 0; if (n_ssids) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { @@ -9103,6 +9135,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct wireless_dev *wdev = info->user_ptr[1]; struct cfg80211_chan_def chandef; + const struct cfg80211_chan_def *compat_chandef; struct sk_buff *msg; void *hdr; u64 cookie; @@ -9131,6 +9164,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, if (err) return err; + wdev_lock(wdev); + if (!cfg80211_off_channel_oper_allowed(wdev) && + !cfg80211_chandef_identical(>chandef, )) { + compat_chandef = cfg80211_chandef_compatible(>chandef, +); + if (compat_chandef != ) { + wdev_unlock(wdev); + return -EBUSY; + } + } + wdev_unlock(wdev); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; @@ -9306,6 +9351,13 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) if (!chandef.chan && params.offchan) return -EINVAL; + wdev_lock(wdev); + if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) { + wdev_unlock(wdev); + return -EBUSY; + } + wdev_unlock(wdev); + params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); -- 1.9.1
[PATCH V2 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain
Sharing DFS channel state across multiple wiphys (radios) could be useful with multiple radios on the system. When one radio completes CAC and markes the channel available another radio can use this information and start beaconing without really doing CAC. Whenever there is a state change in dfs channel associated to a particular wiphy the the same state change is propagated to other wiphys having the same DFS reg domain configuration. Also when a new wiphy is created the dfs channel state of other existing wiphys of same DFS domain is copied. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- V2: - Add a sanity check on the chandef in regulatory_propagate_dfs_state() to make sure the channel is valid before proceeding with dfs state propagation for the channel. net/wireless/chan.c | 30 ++--- net/wireless/core.c | 37 net/wireless/core.h | 6 +++ net/wireless/mlme.c | 10 + net/wireless/reg.c | 120 net/wireless/reg.h | 22 ++ 6 files changed, 218 insertions(+), 7 deletions(-) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 099f13c..b8aa5a7 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -531,16 +531,11 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) return active; } -bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, - struct ieee80211_channel *chan) +static bool cfg80211_is_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan) { struct wireless_dev *wdev; - ASSERT_RTNL(); - - if (!(chan->flags & IEEE80211_CHAN_RADAR)) - return false; - list_for_each_entry(wdev, >wdev_list, list) { wdev_lock(wdev); if (!cfg80211_beaconing_iface_active(wdev)) { @@ -558,6 +553,27 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, return false; } +bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan) +{ + struct cfg80211_registered_device *rdev; + + ASSERT_RTNL(); + + if (!(chan->flags & IEEE80211_CHAN_RADAR)) + return false; + + list_for_each_entry(rdev, _rdev_list, list) { + if (!reg_dfs_domain_same(wiphy, >wiphy)) + continue; + + if (cfg80211_is_wiphy_oper_chan(>wiphy, chan)) + return true; + } + + return false; +} + static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, u32 center_freq, u32 bandwidth) diff --git a/net/wireless/core.c b/net/wireless/core.c index 04143df..a5630e9 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -357,6 +357,38 @@ static void cfg80211_sched_scan_stop_wk(struct work_struct *work) rtnl_unlock(); } +static void cfg80211_propagate_radar_detect_wk(struct work_struct *work) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(work, struct cfg80211_registered_device, + propagate_radar_detect_wk); + + rtnl_lock(); + + regulatory_propagate_dfs_state(>wiphy, >radar_chandef, + NL80211_DFS_UNAVAILABLE, + NL80211_RADAR_DETECTED); + + rtnl_unlock(); +} + +static void cfg80211_propagate_cac_done_wk(struct work_struct *work) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(work, struct cfg80211_registered_device, + propagate_cac_done_wk); + + rtnl_lock(); + + regulatory_propagate_dfs_state(>wiphy, >cac_done_chandef, + NL80211_DFS_AVAILABLE, + NL80211_RADAR_CAC_FINISHED); + + rtnl_unlock(); +} + /* exported functions */ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, @@ -456,6 +488,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, spin_lock_init(>destroy_list_lock); INIT_WORK(>destroy_work, cfg80211_destroy_iface_wk); INIT_WORK(>sched_scan_stop_wk, cfg80211_sched_scan_stop_wk); + INIT_WORK(>propagate_radar_detect_wk, + cfg80211_propagate_radar_detect_wk); + INIT_WORK(>propagate_cac_done_wk, cfg80211_propagate_cac_done_wk); #ifdef CONFIG_CFG80211_DEFAULT_PS rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -915,6 +950,8 @@ void wiphy_unregister(struct wiphy *wiphy) flush_work(>destroy_work); flush_work(>sched_scan_stop_wk); flush_work(>mlme_unreg_wk); + flush_work(>propagate_radar_dete
[PATCH V2 1/3] cfg80211: Make pre-CAC results valid only for ETSI domain
DFS requirement for ETSI domain (section 4.7.1.4 in ETSI EN 301 893 V1.8.1) is the only one which explicitly states that once DFS channel is marked as available afer the CAC, this channel will remain in available state even moving to a different operating channel. But the same is not explicitly stated in FCC DFS requirement. Also, Pre-CAC requriements are not explicitly mentioned in FCC requirement. Current implementation in keeping DFS channel in available state is same as described in ETSI domain. For ETSI DFS domain, this patch gives a grace period of 2 seconds since the completion of successful CAC before moving the channel's DFS state to 'usable' from 'available' state. The same grace period is checked against the channel's dfs_state_entered timestamp while deciding if a DFS channel is available for operation. There is a new radar event, NL80211_RADAR_PRE_CAC_EXPIRED, reported when DFS channel is moved from available to usable state after the grace period. Also make sure the DFS channel state is reset to usable once the beaconing operation on that channel is brought down (like stop_ap, leave_ibss and leave_mesh) in non-ETSI domain. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- include/uapi/linux/nl80211.h | 5 +++ net/wireless/ap.c| 5 +++ net/wireless/chan.c | 101 +++ net/wireless/core.h | 10 + net/wireless/ibss.c | 1 + net/wireless/mesh.c | 1 + net/wireless/mlme.c | 40 + net/wireless/reg.c | 28 net/wireless/reg.h | 14 ++ 9 files changed, 196 insertions(+), 9 deletions(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 9a499b1..cd4dfef 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -4913,12 +4913,17 @@ enum nl80211_smps_mode { * change to the channel status. * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is * over, channel becomes usable. + * @NL80211_RADAR_PRE_CAC_EXPIRED: Channel Availability Check done on this + * non-operating channel is expired and no longer valid. New CAC must + * be done on this channel before starting the operation. This is not + * applicable for ETSI dfs domain where pre-CAC is valid for ever. */ enum nl80211_radar_event { NL80211_RADAR_DETECTED, NL80211_RADAR_CAC_FINISHED, NL80211_RADAR_CAC_ABORTED, NL80211_RADAR_NOP_FINISHED, + NL80211_RADAR_PRE_CAC_EXPIRED, }; /** diff --git a/net/wireless/ap.c b/net/wireless/ap.c index bdad1f9..25666d3 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c @@ -32,6 +32,11 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, rdev_set_qos_map(rdev, dev, NULL); if (notify) nl80211_send_ap_stopped(wdev); + + /* Should we apply the grace period during beaconing interface +* shutdown also? +*/ + cfg80211_sched_dfs_chan_update(rdev); } return err; diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 5497d022..099f13c 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -456,6 +456,107 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, return (r1 + r2 > 0); } +/* + * Checks if center frequency of chan falls with in the bandwidth + * range of chandef. + */ +bool cfg80211_is_sub_chan(struct cfg80211_chan_def *chandef, + struct ieee80211_channel *chan) +{ + int width; + u32 cf_offset, freq; + + if (chandef->chan->center_freq == chan->center_freq) + return true; + + width = cfg80211_chandef_get_width(chandef); + if (width <= 20) + return false; + + cf_offset = width / 2 - 10; + + for (freq = chandef->center_freq1 - width / 2 + 10; +freq <= chandef->center_freq1 + width / 2 - 10; freq += 20) { + if (chan->center_freq == freq) + return true; + } + + if (!chandef->center_freq2) + return false; + + for (freq = chandef->center_freq2 - width / 2 + 10; +freq <= chandef->center_freq2 + width / 2 - 10; freq += 20) { + if (chan->center_freq == freq) + return true; + } + + return false; +} + +bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) +{ + bool active = false; + + ASSERT_WDEV_LOCK(wdev); + + if (!wdev->chandef.chan) + return false; + + switch (wdev->iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + active = wdev->beacon_interval != 0; + break; + case NL80211_IFTYPE_ADHOC: + active =
[PATCH V2 0/3] Pre-CAC and sharing DFS state across multiple radios
Currently irrespective of dfs domain and radar detection activity pre-CAC results for a wiphy are retained till the wiphy is detroyed. This may not be preferred in non-ETSI dfs domain where pre-CAC is not explicitly mentioned in the respective DFS requirement spec. This patch set modifies the current behaviour of pre-CAC for non-ETSI domain by giving 2 seconds grace period for dfs master interface to start operating on the CAC completed channel. This patch set also adds support to share dfs channel state across multiple radios of the same regulatory configuration. Vasanthakumar Thiagarajan (3): cfg80211: Make pre-CAC results valid only for ETSI domain cfg80211: Disallow moving out of operating DFS channel in non-ETSI cfg80211: Share Channel DFS state across wiphys of same DFS domain include/uapi/linux/nl80211.h | 5 ++ net/wireless/ap.c| 5 ++ net/wireless/chan.c | 117 ++ net/wireless/core.c | 37 +++ net/wireless/core.h | 16 + net/wireless/ibss.c | 1 + net/wireless/mesh.c | 1 + net/wireless/mlme.c | 50 --- net/wireless/nl80211.c | 52 +++ net/wireless/reg.c | 148 +++ net/wireless/reg.h | 36 +++ 11 files changed, 459 insertions(+), 9 deletions(-) -- 1.9.1
[PATCH 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain
Sharing DFS channel state across multiple wiphys (radios) could be useful with multiple radios on the system. When one radio completes CAC and markes the channel available another radio can use this information and start beaconing without really doing CAC. Whenever there is a state change in dfs channel associated to a particular wiphy the the same state change is propagated to other wiphys having the same DFS reg domain configuration. Also when a new wiphy is created the dfs channel state of other existing wiphys of same DFS domain is copied. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- net/wireless/chan.c | 30 ++ net/wireless/core.c | 37 + net/wireless/core.h | 6 +++ net/wireless/mlme.c | 10 + net/wireless/reg.c | 117 net/wireless/reg.h | 22 ++ 6 files changed, 215 insertions(+), 7 deletions(-) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 099f13c..b8aa5a7 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -531,16 +531,11 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) return active; } -bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, - struct ieee80211_channel *chan) +static bool cfg80211_is_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan) { struct wireless_dev *wdev; - ASSERT_RTNL(); - - if (!(chan->flags & IEEE80211_CHAN_RADAR)) - return false; - list_for_each_entry(wdev, >wdev_list, list) { wdev_lock(wdev); if (!cfg80211_beaconing_iface_active(wdev)) { @@ -558,6 +553,27 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, return false; } +bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan) +{ + struct cfg80211_registered_device *rdev; + + ASSERT_RTNL(); + + if (!(chan->flags & IEEE80211_CHAN_RADAR)) + return false; + + list_for_each_entry(rdev, _rdev_list, list) { + if (!reg_dfs_domain_same(wiphy, >wiphy)) + continue; + + if (cfg80211_is_wiphy_oper_chan(>wiphy, chan)) + return true; + } + + return false; +} + static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, u32 center_freq, u32 bandwidth) diff --git a/net/wireless/core.c b/net/wireless/core.c index 04143df..a5630e9 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -357,6 +357,38 @@ static void cfg80211_sched_scan_stop_wk(struct work_struct *work) rtnl_unlock(); } +static void cfg80211_propagate_radar_detect_wk(struct work_struct *work) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(work, struct cfg80211_registered_device, + propagate_radar_detect_wk); + + rtnl_lock(); + + regulatory_propagate_dfs_state(>wiphy, >radar_chandef, + NL80211_DFS_UNAVAILABLE, + NL80211_RADAR_DETECTED); + + rtnl_unlock(); +} + +static void cfg80211_propagate_cac_done_wk(struct work_struct *work) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(work, struct cfg80211_registered_device, + propagate_cac_done_wk); + + rtnl_lock(); + + regulatory_propagate_dfs_state(>wiphy, >cac_done_chandef, + NL80211_DFS_AVAILABLE, + NL80211_RADAR_CAC_FINISHED); + + rtnl_unlock(); +} + /* exported functions */ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, @@ -456,6 +488,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, spin_lock_init(>destroy_list_lock); INIT_WORK(>destroy_work, cfg80211_destroy_iface_wk); INIT_WORK(>sched_scan_stop_wk, cfg80211_sched_scan_stop_wk); + INIT_WORK(>propagate_radar_detect_wk, + cfg80211_propagate_radar_detect_wk); + INIT_WORK(>propagate_cac_done_wk, cfg80211_propagate_cac_done_wk); #ifdef CONFIG_CFG80211_DEFAULT_PS rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -915,6 +950,8 @@ void wiphy_unregister(struct wiphy *wiphy) flush_work(>destroy_work); flush_work(>sched_scan_stop_wk); flush_work(>mlme_unreg_wk); + flush_work(>propagate_radar_detect_wk); + flush_work(>propagate_cac_done_wk); #ifdef CONFIG_PM if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) diff --git a/net/wireless/core.h b/net/wirele
[PATCH 1/3] cfg80211: Make pre-CAC results valid only for ETSI domain
DFS requirement for ETSI domain (section 4.7.1.4 in ETSI EN 301 893 V1.8.1) is the only one which explicitly states that once DFS channel is marked as available afer the CAC, this channel will remain in available state even moving to a different operating channel. But the same is not explicitly stated in FCC DFS requirement. Also, Pre-CAC requriements are not explicitly mentioned in FCC requirement. Current implementation in keeping DFS channel in available state is same as described in ETSI domain. For ETSI DFS domain, this patch gives a grace period of 2 seconds since the completion of successful CAC before moving the channel's DFS state to 'usable' from 'available' state. The same grace period is checked against the channel's dfs_state_entered timestamp while deciding if a DFS channel is available for operation. There is a new radar event, NL80211_RADAR_PRE_CAC_EXPIRED, reported when DFS channel is moved from available to usable state after the grace period. Also make sure the DFS channel state is reset to usable once the beaconing operation on that channel is brought down (like stop_ap, leave_ibss and leave_mesh) in non-ETSI domain. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- include/uapi/linux/nl80211.h | 5 +++ net/wireless/ap.c| 5 +++ net/wireless/chan.c | 101 +++ net/wireless/core.h | 10 + net/wireless/ibss.c | 1 + net/wireless/mesh.c | 1 + net/wireless/mlme.c | 40 + net/wireless/reg.c | 28 net/wireless/reg.h | 14 ++ 9 files changed, 196 insertions(+), 9 deletions(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 9a499b1..cd4dfef 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -4913,12 +4913,17 @@ enum nl80211_smps_mode { * change to the channel status. * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is * over, channel becomes usable. + * @NL80211_RADAR_PRE_CAC_EXPIRED: Channel Availability Check done on this + * non-operating channel is expired and no longer valid. New CAC must + * be done on this channel before starting the operation. This is not + * applicable for ETSI dfs domain where pre-CAC is valid for ever. */ enum nl80211_radar_event { NL80211_RADAR_DETECTED, NL80211_RADAR_CAC_FINISHED, NL80211_RADAR_CAC_ABORTED, NL80211_RADAR_NOP_FINISHED, + NL80211_RADAR_PRE_CAC_EXPIRED, }; /** diff --git a/net/wireless/ap.c b/net/wireless/ap.c index bdad1f9..25666d3 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c @@ -32,6 +32,11 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, rdev_set_qos_map(rdev, dev, NULL); if (notify) nl80211_send_ap_stopped(wdev); + + /* Should we apply the grace period during beaconing interface +* shutdown also? +*/ + cfg80211_sched_dfs_chan_update(rdev); } return err; diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 5497d022..099f13c 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -456,6 +456,107 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, return (r1 + r2 > 0); } +/* + * Checks if center frequency of chan falls with in the bandwidth + * range of chandef. + */ +bool cfg80211_is_sub_chan(struct cfg80211_chan_def *chandef, + struct ieee80211_channel *chan) +{ + int width; + u32 cf_offset, freq; + + if (chandef->chan->center_freq == chan->center_freq) + return true; + + width = cfg80211_chandef_get_width(chandef); + if (width <= 20) + return false; + + cf_offset = width / 2 - 10; + + for (freq = chandef->center_freq1 - width / 2 + 10; +freq <= chandef->center_freq1 + width / 2 - 10; freq += 20) { + if (chan->center_freq == freq) + return true; + } + + if (!chandef->center_freq2) + return false; + + for (freq = chandef->center_freq2 - width / 2 + 10; +freq <= chandef->center_freq2 + width / 2 - 10; freq += 20) { + if (chan->center_freq == freq) + return true; + } + + return false; +} + +bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) +{ + bool active = false; + + ASSERT_WDEV_LOCK(wdev); + + if (!wdev->chandef.chan) + return false; + + switch (wdev->iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + active = wdev->beacon_interval != 0; + break; + case NL80211_IFTYPE_ADHOC: + active =
[PATCH 2/3] cfg80211: Disallow moving out of operating DFS channel in non-ETSI
For non-ETSI regulatory domain, CAC result on DFS channel may not be valid once moving out of that channel (as done during remain-on-channel, scannning and off-channel tx). Running CAC on an operating DFS channel after every off-channel operation will only add complexity and disturb the current link. Better do not allow any off-channel switch from a DFS operating channel in non-ETSI domain. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- net/wireless/nl80211.c | 52 ++ 1 file changed, 52 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d516527..b15903b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6556,6 +6556,19 @@ static int nl80211_parse_random_mac(struct nlattr **attrs, return 0; } +static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev) +{ + ASSERT_WDEV_LOCK(wdev); + + if (!cfg80211_beaconing_iface_active(wdev)) + return true; + + if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR)) + return true; + + return regulatory_pre_cac_allowed(wdev->wiphy); +} + static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -6681,6 +6694,25 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) request->n_channels = i; + wdev_lock(wdev); + if (!cfg80211_off_channel_oper_allowed(wdev)) { + struct ieee80211_channel *chan; + + if (request->n_channels != 1) { + wdev_unlock(wdev); + err = -EBUSY; + goto out_free; + } + + chan = request->channels[0]; + if (chan->center_freq != wdev->chandef.chan->center_freq) { + wdev_unlock(wdev); + err = -EBUSY; + goto out_free; + } + } + wdev_unlock(wdev); + i = 0; if (n_ssids) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { @@ -9103,6 +9135,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct wireless_dev *wdev = info->user_ptr[1]; struct cfg80211_chan_def chandef; + const struct cfg80211_chan_def *compat_chandef; struct sk_buff *msg; void *hdr; u64 cookie; @@ -9131,6 +9164,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, if (err) return err; + wdev_lock(wdev); + if (!cfg80211_off_channel_oper_allowed(wdev) && + !cfg80211_chandef_identical(>chandef, )) { + compat_chandef = cfg80211_chandef_compatible(>chandef, +); + if (compat_chandef != ) { + wdev_unlock(wdev); + return -EBUSY; + } + } + wdev_unlock(wdev); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; @@ -9306,6 +9351,13 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) if (!chandef.chan && params.offchan) return -EINVAL; + wdev_lock(wdev); + if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) { + wdev_unlock(wdev); + return -EBUSY; + } + wdev_unlock(wdev); + params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); -- 1.9.1
[PATCH 0/3] Pre-CAC and sharing DFS state across multiple radios
Currently irrespective of dfs domain and radar detection activity pre-CAC results for a wiphy are retained till the wiphy is detroyed. This may not be preferred in non-ETSI dfs domain where pre-CAC is not explicitly mentioned in the respective DFS requirement spec. This patch set modifies the current behaviour of pre-CAC for non-ETSI domain by giving 2 seconds grace period for dfs master interface to start operating on the CAC completed channel. This patch set also adds support to share dfs channel state across multiple radios of the same regulatory configuration. Vasanthakumar Thiagarajan (3): cfg80211: Make pre-CAC results valid only for ETSI domain cfg80211: Disallow moving out of operating DFS channel in non-ETSI cfg80211: Share Channel DFS state across wiphys of same DFS domain include/uapi/linux/nl80211.h | 5 ++ net/wireless/ap.c| 5 ++ net/wireless/chan.c | 117 ++ net/wireless/core.c | 37 +++ net/wireless/core.h | 16 + net/wireless/ibss.c | 1 + net/wireless/mesh.c | 1 + net/wireless/mlme.c | 50 --- net/wireless/nl80211.c | 52 net/wireless/reg.c | 145 +++ net/wireless/reg.h | 36 +++ 11 files changed, 456 insertions(+), 9 deletions(-) -- 1.9.1
[RFC V2 2/3] cfg80211: Disallow moving out of operating DFS channel in non-ETSI
For non-ETSI regulatory domain, CAC result on DFS channel may not be valid once moving out of that channel (as done during remain-on-channel, scannning and off-channel tx). Running CAC on an operating DFS channel after every off-channel operation will only add complexity and disturb the current link. Better do not allow any off-channel switch from a DFS operating channel in non-ETSI domain. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- V2: Addressing below comments from Johannes - Add locking assertion to cfg80211_off_channel_oper_allowed() - Protect wdev->chandef access with wdev_lock() net/wireless/nl80211.c | 52 ++ 1 file changed, 52 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 63dfa60..94c84bd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6506,6 +6506,19 @@ static int nl80211_parse_random_mac(struct nlattr **attrs, return 0; } +static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev) +{ + ASSERT_WDEV_LOCK(wdev); + + if (!cfg80211_beaconing_iface_active(wdev)) + return true; + + if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR)) + return true; + + return regulatory_pre_cac_allowed(wdev->wiphy); +} + static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -6631,6 +6644,25 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) request->n_channels = i; + wdev_lock(wdev); + if (!cfg80211_off_channel_oper_allowed(wdev)) { + struct ieee80211_channel *chan; + + if (request->n_channels != 1) { + wdev_unlock(wdev); + err = -EBUSY; + goto out_free; + } + + chan = request->channels[0]; + if (chan->center_freq != wdev->chandef.chan->center_freq) { + wdev_unlock(wdev); + err = -EBUSY; + goto out_free; + } + } + wdev_unlock(wdev); + i = 0; if (n_ssids) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { @@ -9053,6 +9085,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct wireless_dev *wdev = info->user_ptr[1]; struct cfg80211_chan_def chandef; + const struct cfg80211_chan_def *compat_chandef; struct sk_buff *msg; void *hdr; u64 cookie; @@ -9081,6 +9114,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, if (err) return err; + wdev_lock(wdev); + if (!cfg80211_off_channel_oper_allowed(wdev) && + !cfg80211_chandef_identical(>chandef, )) { + compat_chandef = cfg80211_chandef_compatible(>chandef, +); + if (compat_chandef != ) { + wdev_unlock(wdev); + return -EBUSY; + } + } + wdev_unlock(wdev); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; @@ -9256,6 +9301,13 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) if (!chandef.chan && params.offchan) return -EINVAL; + wdev_lock(wdev); + if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) { + wdev_unlock(wdev); + return -EBUSY; + } + wdev_unlock(wdev); + params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); -- 1.9.1
[RFC V2 1/3] cfg80211: Make pre-CAC results valid only for ETSI domain
DFS requirement for ETSI domain (section 4.7.1.4 in ETSI EN 301 893 V1.8.1) is the only one which explicitly states that once DFS channel is marked as available afer the CAC, this channel will remain in available state even moving to a different operating channel. But the same is not explicitly stated in FCC DFS requirement. Also, Pre-CAC requriements are not explicitly mentioned in FCC requirement. Current implementation in keeping DFS channel in available state is same as described in ETSI domain. For ETSI DFS domain, this patch gives a grace period of 2 seconds since the completion of successful CAC before moving the channel's DFS state to 'usable' from 'available' state. The same grace period is checked against the channel's dfs_state_entered timestamp while deciding if a DFS channel is available for operation. There is a new radar event, NL80211_RADAR_PRE_CAC_EXPIRED, reported when DFS channel is moved from available to usable state after the grace period. Also make sure the DFS channel state is reset to usable once the beaconing operation on that channel is brought down (like stop_ap, leave_ibss and leave_mesh) in non-ETSI domain. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- V2: Address below comments from Johannes - Make 5G specific function names generic - Rewrite helper function which checks if the 20Mhz channel in operating bandwidth with comment. - Remove regulatory_get_pre_cac_timeout() and use regulatory_pre_cac_allowed() directly. include/uapi/linux/nl80211.h | 5 +++ net/wireless/ap.c| 5 +++ net/wireless/chan.c | 101 +++ net/wireless/core.h | 10 + net/wireless/ibss.c | 1 + net/wireless/mesh.c | 1 + net/wireless/mlme.c | 40 + net/wireless/reg.c | 28 net/wireless/reg.h | 14 ++ 9 files changed, 196 insertions(+), 9 deletions(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index d6c62ee..9d2d2b1 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -4893,12 +4893,17 @@ enum nl80211_smps_mode { * change to the channel status. * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is * over, channel becomes usable. + * @NL80211_RADAR_PRE_CAC_EXPIRED: Channel Availability Check done on this + * non-operating channel is expired and no longer valid. New CAC must + * be done on this channel before starting the operation. This is not + * applicable for ETSI dfs domain where pre-CAC is valid for ever. */ enum nl80211_radar_event { NL80211_RADAR_DETECTED, NL80211_RADAR_CAC_FINISHED, NL80211_RADAR_CAC_ABORTED, NL80211_RADAR_NOP_FINISHED, + NL80211_RADAR_PRE_CAC_EXPIRED, }; /** diff --git a/net/wireless/ap.c b/net/wireless/ap.c index bdad1f9..25666d3 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c @@ -32,6 +32,11 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, rdev_set_qos_map(rdev, dev, NULL); if (notify) nl80211_send_ap_stopped(wdev); + + /* Should we apply the grace period during beaconing interface +* shutdown also? +*/ + cfg80211_sched_dfs_chan_update(rdev); } return err; diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 5497d022..099f13c 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -456,6 +456,107 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, return (r1 + r2 > 0); } +/* + * Checks if center frequency of chan falls with in the bandwidth + * range of chandef. + */ +bool cfg80211_is_sub_chan(struct cfg80211_chan_def *chandef, + struct ieee80211_channel *chan) +{ + int width; + u32 cf_offset, freq; + + if (chandef->chan->center_freq == chan->center_freq) + return true; + + width = cfg80211_chandef_get_width(chandef); + if (width <= 20) + return false; + + cf_offset = width / 2 - 10; + + for (freq = chandef->center_freq1 - width / 2 + 10; +freq <= chandef->center_freq1 + width / 2 - 10; freq += 20) { + if (chan->center_freq == freq) + return true; + } + + if (!chandef->center_freq2) + return false; + + for (freq = chandef->center_freq2 - width / 2 + 10; +freq <= chandef->center_freq2 + width / 2 - 10; freq += 20) { + if (chan->center_freq == freq) + return true; + } + + return false; +} + +bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) +{ + bool active = false; + + ASSERT_WD
[RFC V2 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain
Sharing DFS channel state across multiple wiphys (radios) could be useful with multiple radios on the system. When one radio completes CAC and markes the channel available another radio can use this information and start beaconing without really doing CAC. Whenever there is a state change in dfs channel associated to a particular wiphy the the same state change is propagated to other wiphys having the same DFS reg domain configuration. Also when a new wiphy is created the dfs channel state of other existing wiphys of same DFS domain is copied. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- V2: - Make 5G specific DFS chan state share logic generic (Johannes) net/wireless/chan.c | 30 ++ net/wireless/core.c | 37 + net/wireless/core.h | 6 +++ net/wireless/mlme.c | 10 + net/wireless/reg.c | 117 net/wireless/reg.h | 22 ++ 6 files changed, 215 insertions(+), 7 deletions(-) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 099f13c..b8aa5a7 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -531,16 +531,11 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) return active; } -bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, - struct ieee80211_channel *chan) +static bool cfg80211_is_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan) { struct wireless_dev *wdev; - ASSERT_RTNL(); - - if (!(chan->flags & IEEE80211_CHAN_RADAR)) - return false; - list_for_each_entry(wdev, >wdev_list, list) { wdev_lock(wdev); if (!cfg80211_beaconing_iface_active(wdev)) { @@ -558,6 +553,27 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, return false; } +bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan) +{ + struct cfg80211_registered_device *rdev; + + ASSERT_RTNL(); + + if (!(chan->flags & IEEE80211_CHAN_RADAR)) + return false; + + list_for_each_entry(rdev, _rdev_list, list) { + if (!reg_dfs_domain_same(wiphy, >wiphy)) + continue; + + if (cfg80211_is_wiphy_oper_chan(>wiphy, chan)) + return true; + } + + return false; +} + static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, u32 center_freq, u32 bandwidth) diff --git a/net/wireless/core.c b/net/wireless/core.c index 903fc419..d61c408 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -357,6 +357,38 @@ static void cfg80211_sched_scan_stop_wk(struct work_struct *work) rtnl_unlock(); } +static void cfg80211_propagate_radar_detect_wk(struct work_struct *work) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(work, struct cfg80211_registered_device, + propagate_radar_detect_wk); + + rtnl_lock(); + + regulatory_propagate_dfs_state(>wiphy, >radar_chandef, + NL80211_DFS_UNAVAILABLE, + NL80211_RADAR_DETECTED); + + rtnl_unlock(); +} + +static void cfg80211_propagate_cac_done_wk(struct work_struct *work) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(work, struct cfg80211_registered_device, + propagate_cac_done_wk); + + rtnl_lock(); + + regulatory_propagate_dfs_state(>wiphy, >cac_done_chandef, + NL80211_DFS_AVAILABLE, + NL80211_RADAR_CAC_FINISHED); + + rtnl_unlock(); +} + /* exported functions */ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, @@ -456,6 +488,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, spin_lock_init(>destroy_list_lock); INIT_WORK(>destroy_work, cfg80211_destroy_iface_wk); INIT_WORK(>sched_scan_stop_wk, cfg80211_sched_scan_stop_wk); + INIT_WORK(>propagate_radar_detect_wk, + cfg80211_propagate_radar_detect_wk); + INIT_WORK(>propagate_cac_done_wk, cfg80211_propagate_cac_done_wk); #ifdef CONFIG_CFG80211_DEFAULT_PS rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -914,6 +949,8 @@ void wiphy_unregister(struct wiphy *wiphy) flush_work(>destroy_work); flush_work(>sched_scan_stop_wk); flush_work(>mlme_unreg_wk); + flush_work(>propagate_radar_detect_wk); + flush_work(>propagate_cac_done_wk); #ifdef CONFIG_PM if (rdev->wiphy.wowlan_config &am
[RFC V2 0/3] Pre-CAC and sharing DFS state across multiple radios
Currently irrespective of dfs domain and radar detection activity pre-CAC results for a wiphy are retained till the wiphy is detroyed. This may not be preferred in non-ETSI dfs domain where pre-CAC is not explicitly mentioned in the respective DFS requirement spec. This patch set modifies the current behaviour of pre-CAC for non-ETSI domain by giving 2 seconds grace period for dfs master interface to start operating on the CAC completed channel. This patch set also adds support to share dfs channel state across multiple radios of the same regulatory configuration. Vasanthakumar Thiagarajan (3): cfg80211: Make pre-CAC results valid only for ETSI domain cfg80211: Disallow moving out of operating DFS channel in non-ETSI cfg80211: Share Channel DFS state across wiphys of same DFS domain include/uapi/linux/nl80211.h | 5 ++ net/wireless/ap.c| 5 ++ net/wireless/chan.c | 117 ++ net/wireless/core.c | 37 +++ net/wireless/core.h | 16 + net/wireless/ibss.c | 1 + net/wireless/mesh.c | 1 + net/wireless/mlme.c | 50 --- net/wireless/nl80211.c | 52 net/wireless/reg.c | 145 +++ net/wireless/reg.h | 36 +++ 11 files changed, 456 insertions(+), 9 deletions(-) -- 1.9.1
[RFC 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain
Sharing DFS channel state across multiple wiphys (radios) could be useful with multiple radios on the system. When one radio completes CAC and marks the channel available another radio can use this information and start beaconing without really doing CAC. Whenever there is a state change in DFS channel associated to a particular wiphy the the same state change is propagated to other wiphys having the same DFS reg domain configuration. Also when a new wiphy is created the DFS channel state of other existing wiphys of same DFS domain is copied. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- net/wireless/chan.c | 24 +-- net/wireless/core.c | 37 + net/wireless/core.h | 6 +++ net/wireless/mlme.c | 11 +- net/wireless/reg.c | 112 net/wireless/reg.h | 22 +++ 6 files changed, 207 insertions(+), 5 deletions(-) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 090309a..40f1097 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -532,21 +532,37 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) return active; } +static bool cfg80211_5ghz_is_wiphy_oper_chan(struct wiphy *wiphy, +struct ieee80211_channel *chan) +{ + struct wireless_dev *wdev; + + list_for_each_entry(wdev, >wdev_list, list) { + if (!cfg80211_beaconing_iface_active(wdev)) + continue; + + if (cfg80211_5ghz_sub_chan(>chandef, chan)) + return true; + } + + return false; +} + bool cfg80211_5ghz_any_wiphy_oper_chan(struct wiphy *wiphy, struct ieee80211_channel *chan) { - struct wireless_dev *wdev; + struct cfg80211_registered_device *rdev; ASSERT_RTNL(); if (!(chan->flags & IEEE80211_CHAN_RADAR)) return false; - list_for_each_entry(wdev, >wdev_list, list) { - if (!cfg80211_beaconing_iface_active(wdev)) + list_for_each_entry(rdev, _rdev_list, list) { + if (!reg_dfs_domain_same(wiphy, >wiphy)) continue; - if (cfg80211_5ghz_sub_chan(>chandef, chan)) + if (cfg80211_5ghz_is_wiphy_oper_chan(>wiphy, chan)) return true; } diff --git a/net/wireless/core.c b/net/wireless/core.c index 903fc419..c3fe44b 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -357,6 +357,38 @@ static void cfg80211_sched_scan_stop_wk(struct work_struct *work) rtnl_unlock(); } +static void cfg80211_propagate_radar_detect_wk(struct work_struct *work) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(work, struct cfg80211_registered_device, + porpagate_radar_detect_wk); + + rtnl_lock(); + + regulatory_propagate_dfs_state(>wiphy, >radar_chandef, + NL80211_DFS_UNAVAILABLE, + NL80211_RADAR_DETECTED); + + rtnl_unlock(); +} + +static void cfg80211_propagate_cac_done_wk(struct work_struct *work) +{ + struct cfg80211_registered_device *rdev; + + rdev = container_of(work, struct cfg80211_registered_device, + propagate_cac_done_wk); + + rtnl_lock(); + + regulatory_propagate_dfs_state(>wiphy, >cac_done_chandef, + NL80211_DFS_AVAILABLE, + NL80211_RADAR_CAC_FINISHED); + + rtnl_unlock(); +} + /* exported functions */ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, @@ -456,6 +488,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, spin_lock_init(>destroy_list_lock); INIT_WORK(>destroy_work, cfg80211_destroy_iface_wk); INIT_WORK(>sched_scan_stop_wk, cfg80211_sched_scan_stop_wk); + INIT_WORK(>porpagate_radar_detect_wk, + cfg80211_propagate_radar_detect_wk); + INIT_WORK(>propagate_cac_done_wk, cfg80211_propagate_cac_done_wk); #ifdef CONFIG_CFG80211_DEFAULT_PS rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -914,6 +949,8 @@ void wiphy_unregister(struct wiphy *wiphy) flush_work(>destroy_work); flush_work(>sched_scan_stop_wk); flush_work(>mlme_unreg_wk); + flush_work(>porpagate_radar_detect_wk); + flush_work(>propagate_cac_done_wk); #ifdef CONFIG_PM if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) diff --git a/net/wireless/core.h b/net/wireless/core.h index 327fe95..607c8be 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -97,6 +97,12 @@ struct cfg80211_registered_device { struct work_struct sch
[RFC 2/3] cfg80211: Disallow moving out of operating DFS channel in non-ETSI
For non-ETSI regulatory domain, CAC result on DFS channel may not be valid once moving out of that channel (as done during remain-on-channel, scannning and off-channel tx). Running CAC on an operating DFS channel after every off-channel operation will only add complexity and disturb the current link. Better do not allow any off-channel switch from a DFS operating channel in non-ETSI domain. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- net/wireless/nl80211.c | 38 ++ 1 file changed, 38 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 63dfa60..c614af4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6506,6 +6506,17 @@ static int nl80211_parse_random_mac(struct nlattr **attrs, return 0; } +static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev) +{ + if (!cfg80211_beaconing_iface_active(wdev)) + return true; + + if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR)) + return true; + + return regulatory_pre_cac_allowed(wdev->wiphy); +} + static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -6631,6 +6642,21 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) request->n_channels = i; + if (!cfg80211_off_channel_oper_allowed(wdev)) { + struct ieee80211_channel *chan; + + if (request->n_channels != 1) { + err = -EBUSY; + goto out_free; + } + + chan = request->channels[0]; + if (chan->center_freq != wdev->chandef.chan->center_freq) { + err = -EBUSY; + goto out_free; + } + } + i = 0; if (n_ssids) { nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { @@ -9053,6 +9079,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct wireless_dev *wdev = info->user_ptr[1]; struct cfg80211_chan_def chandef; + const struct cfg80211_chan_def *compat_chandef; struct sk_buff *msg; void *hdr; u64 cookie; @@ -9081,6 +9108,14 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, if (err) return err; + if (!(cfg80211_off_channel_oper_allowed(wdev) || + cfg80211_chandef_identical(>chandef, ))) { + compat_chandef = cfg80211_chandef_compatible(>chandef, +); + if (compat_chandef != ) + return -EBUSY; + } + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; @@ -9256,6 +9291,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) if (!chandef.chan && params.offchan) return -EINVAL; + if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) + return -EBUSY; + params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); -- 1.9.1
[RFC 1/3] cfg80211: Make pre-CAC results valid only for ETSI domain
DFS requirement for ETSI domain (section 4.7.1.4 in ETSI EN 301 893 V1.8.1) is the only one which explicitly states that once DFS channel is marked as available afer the CAC, this channel will remain in available state even moving to a different operating channel. But the same is not explicitly stated in FCC DFS requirement. Also, Pre-CAC requriements are not explicitly mentioned in FCC requirement. Current implementation in keeping DFS channel in available state is same as described in ETSI domain. For ETSI DFS domain, this patch gives a grace period of 2 seconds since the completion of successful CAC before moving the channel's DFS state to 'usable' from 'available' state. The same grace period is checked against the channel's dfs_state_entered timestamp while deciding if a DFS channel is available for operation. There is a new radar event, NL80211_RADAR_PRE_CAC_EXPIRED, reported when DFS channel is moved from available to usable state after the grace period. Also make sure the DFS channel state is reset to usable once the beaconing operation on that channel is brought down (like stop_ap, leave_ibss and leave_mesh) in non-ETSI domain. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- include/uapi/linux/nl80211.h | 5 +++ net/wireless/ap.c| 5 +++ net/wireless/chan.c | 96 net/wireless/core.h | 7 net/wireless/ibss.c | 1 + net/wireless/mesh.c | 1 + net/wireless/mlme.c | 41 ++- net/wireless/reg.c | 47 ++ net/wireless/reg.h | 14 +++ 9 files changed, 208 insertions(+), 9 deletions(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index d6c62ee..9d2d2b1 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -4893,12 +4893,17 @@ enum nl80211_smps_mode { * change to the channel status. * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is * over, channel becomes usable. + * @NL80211_RADAR_PRE_CAC_EXPIRED: Channel Availability Check done on this + * non-operating channel is expired and no longer valid. New CAC must + * be done on this channel before starting the operation. This is not + * applicable for ETSI dfs domain where pre-CAC is valid for ever. */ enum nl80211_radar_event { NL80211_RADAR_DETECTED, NL80211_RADAR_CAC_FINISHED, NL80211_RADAR_CAC_ABORTED, NL80211_RADAR_NOP_FINISHED, + NL80211_RADAR_PRE_CAC_EXPIRED, }; /** diff --git a/net/wireless/ap.c b/net/wireless/ap.c index bdad1f9..25666d3 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c @@ -32,6 +32,11 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, rdev_set_qos_map(rdev, dev, NULL); if (notify) nl80211_send_ap_stopped(wdev); + + /* Should we apply the grace period during beaconing interface +* shutdown also? +*/ + cfg80211_sched_dfs_chan_update(rdev); } return err; diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 5497d022..090309a 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -456,6 +456,102 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, return (r1 + r2 > 0); } +static bool cfg80211_5ghz_sub_chan(struct cfg80211_chan_def *chandef, + struct ieee80211_channel *chan) +{ + u32 start_freq_seg0 = 0, end_freq_seg0 = 0; + u32 start_freq_seg1 = 0, end_freq_seg1 = 0; + + if (chandef->chan->center_freq == chan->center_freq) + return true; + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_40: + start_freq_seg0 = chandef->center_freq1 - 20; + end_freq_seg0 = chandef->center_freq1 + 20; + break; + case NL80211_CHAN_WIDTH_80P80: + start_freq_seg1 = chandef->center_freq2 - 40; + end_freq_seg1 = chandef->center_freq2 + 40; + /* fall through */ + case NL80211_CHAN_WIDTH_80: + start_freq_seg0 = chandef->center_freq1 - 40; + end_freq_seg0 = chandef->center_freq1 + 40; + break; + case NL80211_CHAN_WIDTH_160: + start_freq_seg0 = chandef->center_freq1 - 80; + end_freq_seg0 = chandef->center_freq1 + 80; + break; + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: + break; + } + + if (chan->center_freq > start_freq_seg0 && + chan->center_freq < end_freq_seg0) + return true; + + return chan->center_freq > start_freq_seg1 && +
[RFC 0/3] Pre-CAC and sharing DFS state across multiple radios
Currently irrespective of dfs domain and radar detection activity pre-CAC results for a wiphy are retained till the wiphy is detroyed. This may not be preferred in non-ETSI dfs domain where pre-CAC is not explicitly mentioned in the respective DFS requirement spec. This patch set modifies the current behaviour of pre-CAC for non-ETSI domain by giving 2 seconds grace period for dfs master interface to start operating on the CAC completed channel. This patch set also adds support to share dfs channel state across multiple radios of the same regulatory configuration. Vasanthakumar Thiagarajan (3): cfg80211: Make pre-CAC results valid only for ETSI domain cfg80211: Disallow moving out of operating DFS channel in non-ETSI cfg80211: Share Channel DFS state across wiphys of same DFS domain include/uapi/linux/nl80211.h | 5 ++ net/wireless/ap.c| 5 ++ net/wireless/chan.c | 112 ++ net/wireless/core.c | 37 ++ net/wireless/core.h | 13 net/wireless/ibss.c | 1 + net/wireless/mesh.c | 1 + net/wireless/mlme.c | 52 +++--- net/wireless/nl80211.c | 38 +++ net/wireless/reg.c | 159 +++ net/wireless/reg.h | 36 ++ 11 files changed, 449 insertions(+), 10 deletions(-) -- 1.9.1
[RFC 3/3] mac80211: Add receive path for ethernet frame format
Implement rx path which does fewer processing on the received data frame which has already gone through 802.11 header decapsulation and other functionalities which require 802.11 header in the low level driver or hardware. Currently this rx path is restricted to AP and STA mode, but can be extended for Adhoc mode as well. This rx path only checks if the driver has advertised it's support of 802.11 header encap/decap offload for data frames. It is upto the low level driver to make sure if the frame that it passes is in ethernet format and the sta pointer is valid. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- include/net/mac80211.h | 19 + net/mac80211/rx.c | 189 - 2 files changed, 206 insertions(+), 2 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 225abaa..75c55e2 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1088,6 +1088,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_ALLOW_SAME_PN: Allow the same PN as same packet before. * This is used for AMSDU subframes which can have the same PN as * the first subframe. + * @RX_FLAG_MCAST: If the receiver address (addr1) in the frame is multicast. + * This is used with the data frames by the drivers supporting 802.11 hdr + * decap offload. */ enum mac80211_rx_flags { RX_FLAG_MMIC_ERROR = BIT(0), @@ -1123,6 +1126,7 @@ enum mac80211_rx_flags { RX_FLAG_RADIOTAP_VENDOR_DATA= BIT(31), RX_FLAG_MIC_STRIPPED= BIT_ULL(32), RX_FLAG_ALLOW_SAME_PN = BIT_ULL(33), + RX_FLAG_MCAST = BIT_ULL(34), }; #define RX_FLAG_STBC_SHIFT 26 @@ -3989,6 +3993,21 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw, } /** + * ieee80211_rx_decap_offl - Receive frames in 802.11 decapsulated format + * + * Low level driver capable of 802.11 header decap uses this function. The frame + * will be in ethernet format. + * This function may not be called in IRQ context. Calls to this function + * for a single hardware must be synchronized against each other. + * + * @hw: the hardware this frame came in on + * @sta : the station the frame was received from, must not be %NULL + * @skb: the buffer to receive, owned by mac80211 after this call + */ +void ieee80211_rx_decap_offl(struct ieee80211_hw *hw, struct ieee80211_sta *sta, +struct sk_buff *skb); + +/** * ieee80211_sta_ps_transition - PS transition for connected sta * * When operating in AP mode with the %IEEE80211_HW_AP_LINK_PS diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2e8a902..3cb8d6e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2103,13 +2103,14 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control) return 0; } +static const u8 pae_group_addr[ETH_ALEN] __aligned(2) + = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; + /* * requires that rx->skb is a frame with ethernet header */ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) { - static const u8 pae_group_addr[ETH_ALEN] __aligned(2) - = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; /* @@ -4180,3 +4181,187 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb) tasklet_schedule(>tasklet); } EXPORT_SYMBOL(ieee80211_rx_irqsafe); + +/* Receive path for decap offloaded data frames */ + +static void +ieee80211_rx_handle_decap_offl(struct ieee80211_sub_if_data *sdata, +struct sta_info *sta, struct sk_buff *skb) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_vif *vif = >vif; + struct net_device *dev = sdata->dev; + struct ieee80211_rx_status *status; + struct ieee80211_key *key = NULL; + struct ieee80211_rx_data rx; + int i; + struct ethhdr *ehdr; + + ehdr = (struct ethhdr *)skb->data; + status = IEEE80211_SKB_RXCB(skb); + + /* TODO: Extend ieee80211_rx_decap_offl() with bssid so that Ethernet +* encap/decap can be supported in Adhoc interface type as well. +* Adhoc interface depends on bssid to udpate last_rx. +*/ + if (vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_AP_VLAN && + vif->type != NL80211_IFTYPE_AP) + goto drop; + + I802_DEBUG_INC(local->dot11ReceivedFragmentCount); + + if (!(status->flag & RX_FLAG_MCAST)) { + sta->rx_stats.last_rx = jiffies; + sta->rx_stats.last_rate = sta_stats_encode_rate(status); + } + + if (sdata->vif.type == NL80211_IFTYPE_STATION && + !is_multicas
[RFC 2/3] mac80211: Implement data xmit for 802.11 encap offload
Driver (or hw) supporting 802.11 encapsulation offload for data frames can make use of this new xmit path. This patch defines new ndo_ops, all these callbacks are same as ieee80211_dataif_ops other than ndo_start_xmit() which does minimal processing leaving 802.11 encap related to driver. This patch makes netdev_ops registration dynamic based on the interface type, at any time the netdev_ops of netdev will be assigned to either the ndo_ops defined to do 802.11 encap or the ones defined for 802.11 encap offload. There is a new hw config notification, IEEE80211_CONF_CHANGE_80211_HDR_OFFL, to make the driver aware of any configuration change in 802.11 encap/decap offload. There is a field, no_80211_encap, added to ieee80211_tx_info:control to mark if the 802.11 encapsulation is offloaded to driver. There is also a new callback for tx completion status indication to handle data frames using 802.11 encap offload. Currently ath10k fw is capable of doing 802.11 encapsulation/decapsulationi offload. With the corresponding driver changes, using 802.11 encap/decap offload might improve performance. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- include/net/mac80211.h | 33 ++- net/mac80211/cfg.c | 8 ++ net/mac80211/ieee80211_i.h | 12 +++ net/mac80211/iface.c | 147 + net/mac80211/key.c | 16 +++- net/mac80211/main.c| 3 + net/mac80211/status.c | 83 - net/mac80211/tx.c | 225 - 8 files changed, 519 insertions(+), 8 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 1e3c8b5..225abaa 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -910,7 +910,12 @@ struct ieee80211_tx_info { }; struct ieee80211_key_conf *hw_key; u32 flags; - /* 4 bytes free */ + /* XXX: This frame is not encaptulated with 802.11 +* header. Should this be added to %IEEE80211_TX_CTRL_* +* flags?. +*/ + bool no_80211_encap; + /* 3 bytes free */ } control; struct { u64 cookie; @@ -1269,6 +1274,8 @@ enum ieee80211_conf_flags { * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed * Note that this is only valid if channel contexts are not used, * otherwise each channel context has the number of chains listed. + * @IEEE80211_CONF_CHANGE_80211_HDR_OFFL: Offload configuration + * implementing 802.11 encap/decap for data frames changed. */ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_SMPS = BIT(1), @@ -1279,6 +1286,7 @@ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), IEEE80211_CONF_CHANGE_IDLE = BIT(8), + IEEE80211_CONF_CHANGE_80211_HDR_OFFL= BIT(9), }; /** @@ -1333,6 +1341,9 @@ enum ieee80211_smps_mode { * configured for an HT channel. * Note that this is only valid if channel contexts are not used, * otherwise each channel context has the number of chains listed. + * + * @encap_decap_80211_offloaded: Whether 802.11 header encap/decap offload + * is enabled */ struct ieee80211_conf { u32 flags; @@ -1346,6 +1357,7 @@ struct ieee80211_conf { struct cfg80211_chan_def chandef; bool radar_enabled; enum ieee80211_smps_mode smps_mode; + bool encap_decap_80211_offloaded; }; /** @@ -4178,6 +4190,25 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb); /** + * ieee80211_tx_status_8023 - transmit status callback for 802.3 frame format + * + * Call this function for all transmitted data frames after their transmit + * completion. This callback should only be called for data frames which + * are are using driver's (or hardware's) offload capability of encap/decap + * 802.11 frames. + * + * This function may not be called in IRQ context. Calls to this function + * for a single hardware must be synchronized against each other. + * + * @hw: the hardware the frame was transmitted by + * @vif: the interface for which the frame was transmitted + * @skb: the frame that was transmitted, owned by mac80211 after this call + */ +void ieee80211_tx_status_8023(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct sk_buff *skb); + +/** * ieee80211_report_low_ack - report non-responding station * * When operating in AP-mode, call this function to report a non-responding diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 47e99ab8..0e53873 100644 --- a/net/mac80211
[RFC 1/3] mac80211: Add provision for 802.11 encap/decap offload
Drivers can have the capability to offload 802.11 encap/decap to firmware or hardware for data frames. This patch adds a new hw_flag for driver to advertise the offload support. Drivers advertising the support have also to implement new ieee80211_ops callback, get_vif_80211_hdr_offload(), to notify if the 802.11 encap/decap offload is supported for a particular vif type. Transmit and receive path offloading 802.11 header (including cipher headers) encap/decap for data frames will be implemented in separate patches. Drivers advertising this capability should also implement other functionalities which deal with 802.11 frame format like below - Hardware encryption/Decryption - ADDBA/DELBA offload - Aggregation and deaggregation of A-MSDU offload - Fragmentation and defragmentation offload - Rx reordering of A-MPDU subframe offload - PN/TSC check offload - Rx duplication check offload - Hardware rate control - Powersave offload Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- include/net/mac80211.h| 16 net/mac80211/debugfs.c| 1 + net/mac80211/driver-ops.h | 21 + net/mac80211/main.c | 4 net/mac80211/trace.h | 33 + 5 files changed, 75 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index b4faadb..1e3c8b5 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2014,6 +2014,11 @@ struct ieee80211_txq { * @IEEE80211_HW_TX_FRAG_LIST: Hardware (or driver) supports sending frag_list * skbs, needed for zero-copy software A-MSDU. * + * @IEEE80211_HW_SUPPORTS_80211_ENCAP_DECAP: Hardware/driver supports 802.11 + * encap/decap for data frames. Supporting driver have to implement + * get_vif_80211_encap_decap_offload() to pass if 802.11 encap/decap + * offload is supported for the vif. + * * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays */ enum ieee80211_hw_flags { @@ -2054,6 +2059,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_USES_RSS, IEEE80211_HW_TX_AMSDU, IEEE80211_HW_TX_FRAG_LIST, + IEEE80211_HW_SUPPORTS_80211_ENCAP_DECAP, /* keep last, obviously */ NUM_IEEE80211_HW_FLAGS @@ -3401,6 +3407,12 @@ enum ieee80211_reconfig_type { * synchronization which is needed in case driver has in its RSS queues * pending frames that were received prior to the control path action * currently taken (e.g. disassociation) but are not processed yet. + * + * @get_vif_80211_hdr_offload: Called to check if driver or hardware + * supports 802.11 encap/decap offload for data frames for the vif. + * Drivers implementing this callback should advertise the support + * through hw_flags (%IEEE80211_HW_SUPPORTS_80211_ENCAP_DECAP). + * This callback can sleep. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, @@ -3639,6 +3651,10 @@ struct ieee80211_ops { void (*wake_tx_queue)(struct ieee80211_hw *hw, struct ieee80211_txq *txq); void (*sync_rx_queues)(struct ieee80211_hw *hw); + + int (*get_vif_80211_hdr_offload)(struct ieee80211_hw *hw, +struct ieee80211_vif *vif, +bool is_4addr, bool *supported); }; /** diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 2906c10..f49fea5 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -302,6 +302,7 @@ static const char *hw_flag_names[] = { FLAG(USES_RSS), FLAG(TX_AMSDU), FLAG(TX_FRAG_LIST), + FLAG(SUPPORTS_80211_ENCAP_DECAP), #undef FLAG }; diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 184473c..22847d2 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -1179,4 +1179,25 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local, local->ops->wake_tx_queue(>hw, >txq); } +static inline int +drv_get_vif_80211_hdr_offload(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + bool use_4addr, bool *supported) +{ + int ret = -EOPNOTSUPP; + + might_sleep(); + + if (local->ops->get_vif_80211_hdr_offload) + ret = local->ops->get_vif_80211_hdr_offload(>hw, + >vif, + use_4addr, + supported); + + trace_drv_get_vif_80211_hdr_offload(local, sdata, use_4addr, + *supported, ret); + + return ret; +} + #endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d00ea9b..2095
[RFC 0/3] Add new data path for ethernet frame format
This patch set adds a new data path to offload 802.11 header encap/decap to driver or hardware. Drivers having support for ieee80211 header encap/decap and other offload functionalities which can't be done before encap or after decap can make use of this new data path. Currently it is implemented for STA and AP interface type, this can be extend other interface types like adhoc. With ath10k driver changes using this new Tx/Rx path, 10 - 15% CPU usage and upto ~20Mbps TCP performance improvements are observed with this ethernet data path. This patch set is prepared on a older mac80211 code base on top of commit 7d27a0ba7adc ("cfg80211: Add mesh peer AID setting API"). Sorry, I could not get a chance to rework it on top of latest mac80211 code base. TODO (from initial review): - Consider ieee8011 header and cipher header size also while updating tx/rx stats for ethernet frame format. - Any optimization to reduce the amount of code change. - Improve commit log and doc Vasanthakumar Thiagarajan (3): mac80211: Add provision for 802.11 encap/decap offload mac80211: Implement data xmit for 802.11 encap offload mac80211: Add receive path for ethernet frame format include/net/mac80211.h | 68 +- net/mac80211/cfg.c | 8 ++ net/mac80211/debugfs.c | 1 + net/mac80211/driver-ops.h | 21 + net/mac80211/ieee80211_i.h | 12 +++ net/mac80211/iface.c | 147 + net/mac80211/key.c | 16 +++- net/mac80211/main.c| 7 ++ net/mac80211/rx.c | 189 - net/mac80211/status.c | 83 - net/mac80211/trace.h | 33 +++ net/mac80211/tx.c | 225 - 12 files changed, 800 insertions(+), 10 deletions(-) -- 1.9.1
[PATCH] ath10k: Fix kernel panic due to race in accessing arvif list
arvifs list is traversed within data_lock spin_lock in tasklet context to fill channel information from the corresponding vif. This means any access to arvifs list for add/del operations should also be protected with the same spin_lock to avoid the race. Fix this by performing list add/del on arvfis within the data_lock. This could fix kernel panic something like the below. LR is at ath10k_htt_rx_pktlog_completion_handler+0x100/0xb6c [ath10k_core] PC is at ath10k_htt_rx_pktlog_completion_handler+0x1c0/0xb6c [ath10k_core] Internal error: Oops: 17 [#1] PREEMPT SMP ARM [] (ath10k_htt_rx_pktlog_completion_handler+0x2f4/0xb6c [ath10k_core]) [] (ath10k_htt_txrx_compl_task+0x8b4/0x1188 [ath10k_core]) [] (tasklet_action+0x8c/0xec) [] (__do_softirq+0xdc/0x208) [] (irq_exit+0x84/0xe0) [] (__handle_domain_irq+0x80/0xa0) [] (gic_handle_irq+0x38/0x5c) [] (__irq_svc+0x40/0x74) (gdb) list *(ath10k_htt_rx_pktlog_completion_handler+0x1c0) 0x136c0 is in ath10k_htt_rx_h_channel (drivers/net/wireless/ath/ath10k/htt_rx.c:769) 764 struct cfg80211_chan_def def; 765 766 lockdep_assert_held(>data_lock); 767 768 list_for_each_entry(arvif, >arvifs, list) { 769 if (arvif->vdev_id == vdev_id && 770 ath10k_mac_vif_chan(arvif->vif, ) == 0) 771 return def.chan; 772 } 773 Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/mac.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 2e5d2ca..691b7b5 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4931,7 +4931,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, } ar->free_vdev_map &= ~(1LL << arvif->vdev_id); + spin_lock_bh(>data_lock); list_add(>list, >arvifs); + spin_unlock_bh(>data_lock); /* It makes no sense to have firmware do keepalives. mac80211 already * takes care of this with idle connection polling. @@ -5082,7 +5084,9 @@ err_peer_delete: err_vdev_delete: ath10k_wmi_vdev_delete(ar, arvif->vdev_id); ar->free_vdev_map |= 1LL << arvif->vdev_id; + spin_lock_bh(>data_lock); list_del(>list); + spin_unlock_bh(>data_lock); err: if (arvif->beacon_buf) { @@ -5128,7 +5132,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, arvif->vdev_id, ret); ar->free_vdev_map |= 1LL << arvif->vdev_id; + spin_lock_bh(>data_lock); list_del(>list); + spin_unlock_bh(>data_lock); if (arvif->vdev_type == WMI_VDEV_TYPE_AP || arvif->vdev_type == WMI_VDEV_TYPE_IBSS) { -- 1.9.1
[PATCH] ath10k: Fix rfc1042 header retrieval in QCA4019 with eth decap mode
Chipset from QCA99X0 onwards (QCA99X0, QCA9984, QCA4019 & future) rx_hdr_status is not padded to align in 4-byte boundary. Define a new hw_params field to handle different alignment behaviour between different hw. This patch fixes improper retrieval of rfc1042 header with QCA4019. This patch along with "ath10k: Properly remove padding from the start of rx payload" will fix traffic failure in ethernet decap mode for QCA4019. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.c | 12 drivers/net/wireless/ath/ath10k/htt_rx.c | 5 +++-- drivers/net/wireless/ath/ath10k/hw.h | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 74d0ace..ea6a8f4 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -68,6 +68,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 4, }, { .id = QCA9887_HW_1_0_VERSION, @@ -87,6 +88,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA9887_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 4, }, { .id = QCA6174_HW_2_1_VERSION, @@ -105,6 +107,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 4, }, { .id = QCA6174_HW_2_1_VERSION, @@ -123,6 +126,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 4, }, { .id = QCA6174_HW_3_0_VERSION, @@ -141,6 +145,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 4, }, { .id = QCA6174_HW_3_2_VERSION, @@ -160,6 +165,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 4, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, @@ -183,6 +189,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 1, }, { .id = QCA9984_HW_1_0_DEV_VERSION, @@ -206,6 +213,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 1, }, { .id = QCA9888_HW_2_0_DEV_VERSION, @@ -228,6 +236,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 1, }, { .id = QCA9377_HW_1_0_DEV_VERSION, @@ -246,6 +255,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 4, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -264,6 +274,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 4, }, { .id = QCA4019_HW_1_0_DEV_VERSION, @@ -288,6 +299,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA4019_BOARD_EXT_DATA_SZ, }, .hw_rx_desc_ops = _rx_desc_ops, + .decap_align_bytes = 1, }, }; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 36c4809..97d5b07 1006
[PATCH 3/4] ath10k: Properly remove padding from the start of rx payload
In QCA99X0 (QCA99X0, QCA9984, QCA9888 and QCA4019) family chips, hw adds padding at the begining of the rx payload to make L3 header 4-byte aligned. In the chips doing this type of padding, the number of bytes padded will be indicated through msdu_end:info1. Define a hw_rx_desc_ops wrapper to retrieve the number of padded bytes and use this while doing undecap. This should fix padding related issues with ethernt decap format with QCA99X0, QCA9984, QCA9888 and QCA4019 hw. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/htt_rx.c | 36 +++- drivers/net/wireless/ath/ath10k/hw.h | 9 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 78db5d6..36c4809 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1056,9 +1056,11 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, const u8 first_hdr[64]) { struct ieee80211_hdr *hdr; + struct htt_rx_desc *rxd; size_t hdr_len; u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; + int l3_pad_bytes; /* Delivered decapped frame: * [nwifi 802.11 header] <-- replaced with 802.11 hdr @@ -1072,19 +1074,12 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, */ /* pull decapped header and copy SA & DA */ - if ((ar->hw_params.hw_4addr_pad == ATH10K_HW_4ADDR_PAD_BEFORE) && - ieee80211_has_a4(((struct ieee80211_hdr *)first_hdr)->frame_control)) { - /* The QCA99X0 4 address mode pad 2 bytes at the -* beginning of MSDU -*/ - hdr = (struct ieee80211_hdr *)(msdu->data + 2); - /* The skb length need be extended 2 as the 2 bytes at the tail -* be excluded due to the padding -*/ - skb_put(msdu, 2); - } else { - hdr = (struct ieee80211_hdr *)(msdu->data); - } + rxd = (void *)msdu->data - sizeof(*rxd); + + l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(>hw_params, rxd); + skb_put(msdu, l3_pad_bytes); + + hdr = (struct ieee80211_hdr *)(msdu->data + l3_pad_bytes); hdr_len = ath10k_htt_rx_nwifi_hdrlen(ar, hdr); ether_addr_copy(da, ieee80211_get_DA(hdr)); @@ -1151,6 +1146,8 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, void *rfc1042; u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; + int l3_pad_bytes; + struct htt_rx_desc *rxd; /* Delivered decapped frame: * [eth header] <-- replaced with 802.11 hdr & rfc1042/llc @@ -1161,6 +1158,11 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, if (WARN_ON_ONCE(!rfc1042)) return; + rxd = (void *)msdu->data - sizeof(*rxd); + l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(>hw_params, rxd); + skb_put(msdu, l3_pad_bytes); + skb_pull(msdu, l3_pad_bytes); + /* pull decapped header and copy SA & DA */ eth = (struct ethhdr *)msdu->data; ether_addr_copy(da, eth->h_dest); @@ -1191,6 +1193,8 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar, { struct ieee80211_hdr *hdr; size_t hdr_len; + int l3_pad_bytes; + struct htt_rx_desc *rxd; /* Delivered decapped frame: * [amsdu header] <-- replaced with 802.11 hdr @@ -1198,7 +1202,11 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar, * [payload] */ - skb_pull(msdu, sizeof(struct amsdu_subframe_hdr)); + rxd = (void *)msdu->data - sizeof(*rxd); + l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(>hw_params, rxd); + + skb_put(msdu, l3_pad_bytes); + skb_pull(msdu, sizeof(struct amsdu_subframe_hdr) + l3_pad_bytes); hdr = (struct ieee80211_hdr *)first_hdr; hdr_len = ieee80211_hdrlen(hdr->frame_control); diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index a281544..cdd2ce4 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -423,6 +423,15 @@ struct ath10k_hw_rx_desc_ops { extern const struct ath10k_hw_rx_desc_ops qca988x_rx_desc_ops; extern const struct ath10k_hw_rx_desc_ops qca99x0_rx_desc_ops; +static inline int +ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, + struct htt_rx_desc *rxd) +{ + if (hw->hw_rx_desc_ops->rx_desc_get_l3_pad_bytes) + return hw->hw_rx_desc_ops->rx_desc_get_l3_pad_bytes(rxd); + return 0; +} + /* Target specific defines for MAIN firmware */ #define TARGET_NUM_VDEVS 8 #define T
[PATCH 4/4] ath10k: Remove 4-addr padding related hw_param configuration
hw_4addr_pad was added to handle different types of padding in 4-address rx frame. But this padding is not very specific to 4-address, it can happen even with three address + ethernet decap mode. Since the padding information can be obtained through Rx desc for QCA99X0 and newer chips, this hw_param is not needed any more. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.c | 9 - drivers/net/wireless/ath/ath10k/hw.h | 8 2 files changed, 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 9c5e93b..74d0ace 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -60,7 +60,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, - .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, .cal_data_len = 2116, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, @@ -80,7 +79,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, - .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, .cal_data_len = 2116, .fw = { .dir = QCA9887_HW_1_0_FW_DIR, @@ -117,7 +115,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, - .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, @@ -136,7 +133,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, - .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, .cal_data_len = 8124, .fw = { .dir = QCA6174_HW_3_0_FW_DIR, @@ -155,7 +151,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, - .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, .cal_data_len = 8124, .fw = { /* uses same binaries as hw3.0 */ @@ -177,7 +172,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cck_rate_map_rev2 = true, .channel_counters_freq_hz = 15, .max_probe_resp_desc_thres = 24, - .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, .tx_chain_mask = 0xf, .rx_chain_mask = 0xf, .max_spatial_stream = 4, @@ -201,7 +195,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cck_rate_map_rev2 = true, .channel_counters_freq_hz = 15, .max_probe_resp_desc_thres = 24, - .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, .tx_chain_mask = 0xf, .rx_chain_mask = 0xf, .max_spatial_stream = 4, @@ -224,7 +217,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .continuous_frag_desc = true, .channel_counters_freq_hz = 15, .max_probe_resp_desc_thres = 24, - .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, .tx_chain_mask = 3, .rx_chain_mask = 3, .max_spatial_stream = 2, @@ -285,7 +277,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .cck_rate_map_rev2 = true, .channel_counters_freq_hz = 125000, .max_probe_resp_desc_thres = 24, - .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, .tx_chain_mask = 0x3, .rx_chain_mask = 0x3, .max_spatial_stream = 2, diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index cdd2ce4..1620e76 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -338,11 +338,6 @@ enum ath10k_hw_rate_rev2_cck { ATH10K_HW_RATE_REV2_CCK_SP_11M, }; -enum ath10k_hw_4addr_pad { - ATH10K_HW_4ADDR_PAD_AFTER, - ATH10K_HW_4ADDR_PAD_BEFORE, -}; - enum ath10k_hw_cc_wraparound_type { ATH10K_HW_CC_WRAP_DISABLED = 0, @@ -395,9 +390,6 @@ struct ath10k_hw_params { */ u32 max_probe_resp_desc_thres; - /* The padding bytes's lo
[PATCH 2/4] ath10k: Add provision for Rx descriptor abstraction
There are slight differences in Rx hw descriptor information among different chips. So far driver does not use those new information for any functionalities, but there is one important information which is available from QCA99X0 onwards to indicate the number of bytes that hw padded at the begining of the rx payload and this information is needed to undecap the rx packet. Add an abstraction for Rx desc to make use of the new desc information available. The callback that this patch defines to retrieve the padding bytes will be used in follow-up patch. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.c | 12 drivers/net/wireless/ath/ath10k/hw.c | 13 + drivers/net/wireless/ath/ath10k/hw.h | 12 3 files changed, 37 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index e889829..9c5e93b 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -68,6 +68,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA988X_BOARD_DATA_SZ, .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA9887_HW_1_0_VERSION, @@ -87,6 +88,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA9887_BOARD_DATA_SZ, .board_ext_size = QCA9887_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA6174_HW_2_1_VERSION, @@ -104,6 +106,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA6174_HW_2_1_VERSION, @@ -122,6 +125,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA6174_HW_3_0_VERSION, @@ -140,6 +144,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA6174_HW_3_2_VERSION, @@ -159,6 +164,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, @@ -182,6 +188,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA99X0_BOARD_DATA_SZ, .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA9984_HW_1_0_DEV_VERSION, @@ -205,6 +212,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA99X0_BOARD_DATA_SZ, .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA9888_HW_2_0_DEV_VERSION, @@ -227,6 +235,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA99X0_BOARD_DATA_SZ, .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA9377_HW_1_0_DEV_VERSION, @@ -244,6 +253,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -261,6 +271,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, + .hw_rx_desc_ops = _rx_desc_ops, }, { .id = QCA4019_HW_1_0_DEV_VERSION, @@ -285,6 +296,7 @@ static const struct ath10k_hw_
[PATCH 1/4] ath10k: Move ath10k_hw_params definition to hw.h
This is to prepare for rx descriptor abstraction where we'll be dereferencing ath10k_hw_params member in hw.h. Moreover hw.h looks more suitable to house ath10k_hw_params definition than core.h Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.h | 48 +- drivers/net/wireless/ath/ath10k/hw.h | 48 ++ 2 files changed, 49 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 30ae5bf..5ace413 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -715,53 +715,7 @@ struct ath10k { struct ath10k_htc htc; struct ath10k_htt htt; - struct ath10k_hw_params { - u32 id; - u16 dev_id; - const char *name; - u32 patch_load_addr; - int uart_pin; - u32 otp_exe_param; - - /* Type of hw cycle counter wraparound logic, for more info -* refer enum ath10k_hw_cc_wraparound_type. -*/ - enum ath10k_hw_cc_wraparound_type cc_wraparound_type; - - /* Some of chip expects fragment descriptor to be continuous -* memory for any TX operation. Set continuous_frag_desc flag -* for the hardware which have such requirement. -*/ - bool continuous_frag_desc; - - /* CCK hardware rate table mapping for the newer chipsets -* like QCA99X0, QCA4019 got revised. The CCK h/w rate values -* are in a proper order with respect to the rate/preamble -*/ - bool cck_rate_map_rev2; - - u32 channel_counters_freq_hz; - - /* Mgmt tx descriptors threshold for limiting probe response -* frames. -*/ - u32 max_probe_resp_desc_thres; - - /* The padding bytes's location is different on various chips */ - enum ath10k_hw_4addr_pad hw_4addr_pad; - - u32 tx_chain_mask; - u32 rx_chain_mask; - u32 max_spatial_stream; - u32 cal_data_len; - - struct ath10k_hw_params_fw { - const char *dir; - const char *board; - size_t board_size; - size_t board_ext_size; - } fw; - } hw_params; + struct ath10k_hw_params hw_params; /* contains the firmware images used with ATH10K_FIRMWARE_MODE_NORMAL */ struct ath10k_fw_components normal_mode_fw; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index e014cd7..1315557 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -363,6 +363,54 @@ enum ath10k_hw_cc_wraparound_type { ATH10K_HW_CC_WRAP_SHIFTED_EACH = 2, }; +struct ath10k_hw_params { + u32 id; + u16 dev_id; + const char *name; + u32 patch_load_addr; + int uart_pin; + u32 otp_exe_param; + + /* Type of hw cycle counter wraparound logic, for more info +* refer enum ath10k_hw_cc_wraparound_type. +*/ + enum ath10k_hw_cc_wraparound_type cc_wraparound_type; + + /* Some of chip expects fragment descriptor to be continuous +* memory for any TX operation. Set continuous_frag_desc flag +* for the hardware which have such requirement. +*/ + bool continuous_frag_desc; + + /* CCK hardware rate table mapping for the newer chipsets +* like QCA99X0, QCA4019 got revised. The CCK h/w rate values +* are in a proper order with respect to the rate/preamble +*/ + bool cck_rate_map_rev2; + + u32 channel_counters_freq_hz; + + /* Mgmt tx descriptors threshold for limiting probe response +* frames. +*/ + u32 max_probe_resp_desc_thres; + + /* The padding bytes's location is different on various chips */ + enum ath10k_hw_4addr_pad hw_4addr_pad; + + u32 tx_chain_mask; + u32 rx_chain_mask; + u32 max_spatial_stream; + u32 cal_data_len; + + struct ath10k_hw_params_fw { + const char *dir; + const char *board; + size_t board_size; + size_t board_ext_size; + } fw; +}; + /* Target specific defines for MAIN firmware */ #define TARGET_NUM_VDEVS 8 #define TARGET_NUM_PEER_AST2 -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/4] ath10k: Padding related clean ups in rx
This patch set adds abstraction for rx_hw_desc processing so that we can make use of newer desc fields notifying padding information which is done on rx payload. "ath10k: Properly remove padding from the start of rx payload" fixes padding related bug in ethernet decap mode for QCA99X0, QCA9984 qnd QCA4019 but even fixing this bug will not make ethernet decap mode work, there needs to be some more fix wich would follow this patch series. Vasanthakumar Thiagarajan (4): ath10k: Move ath10k_hw_params definition to hw.h ath10k: Add provision for Rx descriptor abstraction ath10k: Properly remove padding from the start of rx payload ath10k: Remove 4-addr padding related hw_param configuration drivers/net/wireless/ath/ath10k/core.c | 21 ++ drivers/net/wireless/ath/ath10k/core.h | 48 + drivers/net/wireless/ath/ath10k/htt_rx.c | 36 +--- drivers/net/wireless/ath/ath10k/hw.c | 13 ++ drivers/net/wireless/ath/ath10k/hw.h | 71 +--- 5 files changed, 114 insertions(+), 75 deletions(-) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ath10k: Fix possible wrong rx_busy time reporting in QCA4019
As hw cycle counters in QCA4019 wraparound independantly in QCA4019 it is possible cycle counter and rx clear counter would wraparound at the same time. Current logic assumes only one of the counters would wraparound at anytime. Fix this by moving 'else' part to another 'if'. Fixes: 8e100354a98 ("ath10k: fix cycle counter wraparound handling for QCA4019") Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index bd86e7a..7462627 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -198,7 +198,8 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, case ATH10K_HW_CC_WRAP_SHIFTED_EACH: if (cc < cc_prev) cc_fix = 0x7fff; - else + + if (rcc < rcc_prev) rcc_fix = 0x7fff; break; case ATH10K_HW_CC_WRAP_DISABLED: -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] ath10k: Define an enum to enable cycle counter wraparound logic
QCA988X hw implements a different cycle counter wraparound behaviour when compared to QCA4019. To properly handle different wraparound logic for these chipsets replace already available bool hw_params member, has_shifted_cc_wraparound, with an enum which could be extended to handle different wraparound behaviour. This patch keeps the existing logic functionally same and a prepares cycle counter wraparound handling to extend for other chips. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.c | 4 ++-- drivers/net/wireless/ath/ath10k/core.h | 8 +++- drivers/net/wireless/ath/ath10k/hw.c | 4 +++- drivers/net/wireless/ath/ath10k/hw.h | 11 +++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index cedf127..8f66653 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -55,7 +55,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = "qca988x hw2.0", .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, - .has_shifted_cc_wraparound = true, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, @@ -224,7 +224,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = "qca4019 hw1.0", .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR, .uart_pin = 7, - .has_shifted_cc_wraparound = true, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, .otp_exe_param = 0x001, .continuous_frag_desc = true, .channel_counters_freq_hz = 125000, diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 4462c3f..b42b21f 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -710,12 +710,10 @@ struct ath10k { int uart_pin; u32 otp_exe_param; - /* This is true if given HW chip has a quirky Cycle Counter -* wraparound which resets to 0x7fff instead of 0. All -* other CC related counters (e.g. Rx Clear Count) are divided -* by 2 so they never wraparound themselves. + /* Type of hw cycle counter wraparound logic, for more info +* refer enum ath10k_hw_cc_wraparound_type. */ - bool has_shifted_cc_wraparound; + enum ath10k_hw_cc_wraparound_type cc_wraparound_type; /* Some of chip expects fragment descriptor to be continuous * memory for any TX operation. Set continuous_frag_desc flag diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index f544d48..31ec164 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -179,11 +179,13 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) { u32 cc_fix = 0; + enum ath10k_hw_cc_wraparound_type wraparound_type; survey->filled |= SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY; - if (ar->hw_params.has_shifted_cc_wraparound && cc < cc_prev) { + wraparound_type = ar->hw_params.cc_wraparound_type; + if (wraparound_type == ATH10K_HW_CC_WRAP_SHIFTED_ALL && cc < cc_prev) { cc_fix = 0x7fff; survey->filled &= ~SURVEY_INFO_TIME_BUSY; } diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index f41c91c..64e45b2 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -331,6 +331,17 @@ enum ath10k_hw_4addr_pad { ATH10K_HW_4ADDR_PAD_BEFORE, }; +enum ath10k_hw_cc_wraparound_type { + ATH10K_HW_CC_WRAP_DISABLED = 0, + + /* This type is when the HW chip has a quirky Cycle Counter +* wraparound which resets to 0x7fff instead of 0. All +* other CC related counters (e.g. Rx Clear Count) are divided +* by 2 so they never wraparound themselves. +*/ + ATH10K_HW_CC_WRAP_SHIFTED_ALL = 1, +}; + /* Target specific defines for MAIN firmware */ #define TARGET_NUM_VDEVS 8 #define TARGET_NUM_PEER_AST2 -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] ath10k: Fix cycle counter wraparound handling for QCA4019
In QCA4019, cycle counter wraparound is not tied to rx clear counter. Each counter would wraparound individually and after wraparound the respective counter will be reset to 0x7fff while other counter still running unaffected. Define a new wraparound type for this behaviour and handle it separately so that rx clear counter wraparound is also handled just like cycle counter. With this type of wraparound we can accurately compute and report channel active/busy time when any of the counter overflows. Fixes: ee9ca147c59 ("ath10k: Fix survey reporting with QCA4019") Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.c | 2 +- drivers/net/wireless/ath/ath10k/hw.c | 24 drivers/net/wireless/ath/ath10k/hw.h | 9 + 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 8f66653..5ede9a4 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -224,7 +224,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = "qca4019 hw1.0", .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR, .uart_pin = 7, - .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, .otp_exe_param = 0x001, .continuous_frag_desc = true, .channel_counters_freq_hz = 125000, diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 31ec164..bd86e7a 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -179,19 +179,35 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) { u32 cc_fix = 0; + u32 rcc_fix = 0; enum ath10k_hw_cc_wraparound_type wraparound_type; survey->filled |= SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY; wraparound_type = ar->hw_params.cc_wraparound_type; - if (wraparound_type == ATH10K_HW_CC_WRAP_SHIFTED_ALL && cc < cc_prev) { - cc_fix = 0x7fff; - survey->filled &= ~SURVEY_INFO_TIME_BUSY; + + if (cc < cc_prev || rcc < rcc_prev) { + switch (wraparound_type) { + case ATH10K_HW_CC_WRAP_SHIFTED_ALL: + if (cc < cc_prev) { + cc_fix = 0x7fff; + survey->filled &= ~SURVEY_INFO_TIME_BUSY; + } + break; + case ATH10K_HW_CC_WRAP_SHIFTED_EACH: + if (cc < cc_prev) + cc_fix = 0x7fff; + else + rcc_fix = 0x7fff; + break; + case ATH10K_HW_CC_WRAP_DISABLED: + break; + } } cc -= cc_prev - cc_fix; - rcc -= rcc_prev; + rcc -= rcc_prev - rcc_fix; survey->time = CCNT_TO_MSEC(ar, cc); survey->time_busy = CCNT_TO_MSEC(ar, rcc); diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 64e45b2..7657c60 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -340,6 +340,15 @@ enum ath10k_hw_cc_wraparound_type { * by 2 so they never wraparound themselves. */ ATH10K_HW_CC_WRAP_SHIFTED_ALL = 1, + + /* Each hw counter wrapsaround independently. When the +* counter overflows the repestive counter is right shifted +* by 1, i.e reset to 0x7fff, and other counters will be +* running unaffected. In this type of wraparound, it should +* be possible to report accurate Rx busy time unlike the +* first type. +*/ + ATH10K_HW_CC_WRAP_SHIFTED_EACH = 2, }; /* Target specific defines for MAIN firmware */ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ath10k: Fix some of the macro definitions of HTT_RX_IND message
Only five bits are defined to pass tid information in HTT_RX_IND message, so the mask which can be used to extract tid should be 0x1f instead of the current 0x3f. Also, macros which can be used to extract flush_valid and release_valid bits have to be left shifted one bit less because these information follow the tid right after. This patch does not really fix anything functionally because these macros are not used currently. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/htt.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 911c535..430a83e 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -485,10 +485,10 @@ struct htt_mgmt_tx_completion { __le32 status; } __packed; -#define HTT_RX_INDICATION_INFO0_EXT_TID_MASK (0x3F) +#define HTT_RX_INDICATION_INFO0_EXT_TID_MASK (0x1F) #define HTT_RX_INDICATION_INFO0_EXT_TID_LSB (0) -#define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 6) -#define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 7) +#define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 5) +#define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 6) #define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_MASK 0x003F #define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_LSB0 -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] ath10k: Fix survey reporting with QCA4019
In QCA4019, cycle counter wraparound in same fashion as QCA988X. When the cycle counter wraparound it resets to 0x7fff. Set has_shifted_cc_wraparound to true for QCA4019 to enable the code path to handle cycle counter wraparound for consistent survey report. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index e94cb87..f6018be 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -202,6 +202,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = "qca4019 hw1.0", .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR, .uart_pin = 7, + .has_shifted_cc_wraparound = true, .otp_exe_param = 0x001, .continuous_frag_desc = true, .channel_counters_freq_hz = 125000, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] ath10k: suppress warnings when getting wmi peer_rate_code_list event
In 10.4, fw sends WMI PEER_RATECODE_LIST_EVENTID after successful peer_assoc cmd. As of now this event is not of much use and not implemented. Change the debug level and messsage as appropriate to suppress "Unknown eventid: 36898". Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 39a54a5..2a14b16 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5213,6 +5213,7 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) ath10k_wmi_event_vdev_stopped(ar, skb); break; case WMI_10_4_WOW_WAKEUP_HOST_EVENTID: + case WMI_10_4_PEER_RATECODE_LIST_EVENTID: ath10k_dbg(ar, ATH10K_DBG_WMI, "received event id %d not implemented\n", id); break; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4] ath10k: Define rx_ppdu_end for QCA9984
QCA9984 Rx descriptor has two 32-bit words of location information when compared to one 32-bit word in QCA99X0. To handle this difference in rx descriptor ppdu_end, define a new ppdu_end for QCA9984 descriptor which has the new structure to represent rx_location_info. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/rx_desc.h | 46 +++ 1 file changed, 46 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h index 3e7dfaa..9ceebea 100644 --- a/drivers/net/wireless/ath/ath10k/rx_desc.h +++ b/drivers/net/wireless/ath/ath10k/rx_desc.h @@ -996,6 +996,41 @@ struct rx_pkt_end { __le32 phy_timestamp_2; } __packed; +#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_MASK 0x3fff +#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_LSB 0 +#define RX_LOCATION_INFO0_RTT_FAC_VHT_MASK 0x1fff8000 +#define RX_LOCATION_INFO0_RTT_FAC_VHT_LSB 15 +#define RX_LOCATION_INFO0_RTT_STRONGEST_CHAIN_MASK 0xc000 +#define RX_LOCATION_INFO0_RTT_STRONGEST_CHAIN_LSB 30 +#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_STATUSBIT(14) +#define RX_LOCATION_INFO0_RTT_FAC_VHT_STATUS BIT(29) + +#define RX_LOCATION_INFO1_RTT_PREAMBLE_TYPE_MASK 0x000c +#define RX_LOCATION_INFO1_RTT_PREAMBLE_TYPE_LSB2 +#define RX_LOCATION_INFO1_PKT_BW_MASK 0x0030 +#define RX_LOCATION_INFO1_PKT_BW_LSB 4 +#define RX_LOCATION_INFO1_SKIP_P_SKIP_BTCF_MASK0xff00 +#define RX_LOCATION_INFO1_SKIP_P_SKIP_BTCF_LSB 8 +#define RX_LOCATION_INFO1_RTT_MSC_RATE_MASK0x000f +#define RX_LOCATION_INFO1_RTT_MSC_RATE_LSB 16 +#define RX_LOCATION_INFO1_RTT_PBD_LEG_BW_MASK 0x0030 +#define RX_LOCATION_INFO1_RTT_PBD_LEG_BW_LSB 20 +#define RX_LOCATION_INFO1_TIMING_BACKOFF_MASK 0x07c0 +#define RX_LOCATION_INFO1_TIMING_BACKOFF_LSB 22 +#define RX_LOCATION_INFO1_RTT_TX_FRAME_PHASE_MASK 0x1800 +#define RX_LOCATION_INFO1_RTT_TX_FRAME_PHASE_LSB 27 +#define RX_LOCATION_INFO1_RTT_CFR_STATUS BIT(0) +#define RX_LOCATION_INFO1_RTT_CIR_STATUS BIT(1) +#define RX_LOCATION_INFO1_RTT_GI_TYPE BIT(7) +#define RX_LOCATION_INFO1_RTT_MAC_PHY_PHASEBIT(29) +#define RX_LOCATION_INFO1_RTT_TX_DATA_START_X_PHASEBIT(30) +#define RX_LOCATION_INFO1_RX_LOCATION_VALIDBIT(31) + +struct rx_location_info { + __le32 rx_location_info0; /* %RX_LOCATION_INFO0_ */ + __le32 rx_location_info1; /* %RX_LOCATION_INFO1_ */ +} __packed; + enum rx_phy_ppdu_end_info0 { RX_PHY_PPDU_END_INFO0_ERR_RADAR = BIT(2), RX_PHY_PPDU_END_INFO0_ERR_RX_ABORT= BIT(3), @@ -1074,12 +1109,23 @@ struct rx_ppdu_end_qca99x0 { __le16 info1; /* %RX_PPDU_END_INFO1_ */ } __packed; +struct rx_ppdu_end_qca9984 { + struct rx_pkt_end rx_pkt_end; + struct rx_location_info rx_location_info; + struct rx_phy_ppdu_end rx_phy_ppdu_end; + __le32 rx_timing_offset; /* %RX_PPDU_END_RX_TIMING_OFFSET_ */ + __le32 rx_info; /* %RX_PPDU_END_RX_INFO_ */ + __le16 bb_length; + __le16 info1; /* %RX_PPDU_END_INFO1_ */ +} __packed; + struct rx_ppdu_end { struct rx_ppdu_end_common common; union { struct rx_ppdu_end_qca988x qca988x; struct rx_ppdu_end_qca6174 qca6174; struct rx_ppdu_end_qca99x0 qca99x0; + struct rx_ppdu_end_qca9984 qca9984; } __packed; } __packed; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] ath10k: Clean up growing hw checks during safe and full reset
Store pci chip secific reset funtions in struct ath10k_pci as callbacks during early ath10k_pci_probe() and use the callback to perform chip specific resets. This patch essentially adds two callback in ath10k_pci, one for doing soft reset and the other for hard reset. By using callbacks we can get rid of those hw revision checks in ath10k_pci_safe_chip_reset() and ath10k_pci_chip_reset(). As such this patch does not fix any issue. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/pci.c | 44 ++- drivers/net/wireless/ath/ath10k/pci.h | 6 + 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index cdd8a30..6614fd7 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2293,16 +2293,20 @@ static int ath10k_pci_warm_reset(struct ath10k *ar) return 0; } +static int ath10k_pci_qca99x0_soft_chip_reset(struct ath10k *ar) +{ + ath10k_pci_irq_disable(ar); + return ath10k_pci_qca99x0_chip_reset(ar); +} + static int ath10k_pci_safe_chip_reset(struct ath10k *ar) { - if (QCA_REV_988X(ar) || QCA_REV_6174(ar)) { - return ath10k_pci_warm_reset(ar); - } else if (QCA_REV_99X0(ar)) { - ath10k_pci_irq_disable(ar); - return ath10k_pci_qca99x0_chip_reset(ar); - } else { + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + if (!ar_pci->pci_soft_reset) return -ENOTSUPP; - } + + return ar_pci->pci_soft_reset(ar); } static int ath10k_pci_qca988x_chip_reset(struct ath10k *ar) @@ -2437,16 +2441,12 @@ static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar) static int ath10k_pci_chip_reset(struct ath10k *ar) { - if (QCA_REV_988X(ar)) - return ath10k_pci_qca988x_chip_reset(ar); - else if (QCA_REV_6174(ar)) - return ath10k_pci_qca6174_chip_reset(ar); - else if (QCA_REV_9377(ar)) - return ath10k_pci_qca6174_chip_reset(ar); - else if (QCA_REV_99X0(ar)) - return ath10k_pci_qca99x0_chip_reset(ar); - else + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + if (WARN_ON(!ar_pci->pci_hard_reset)) return -ENOTSUPP; + + return ar_pci->pci_hard_reset(ar); } static int ath10k_pci_hif_power_up(struct ath10k *ar) @@ -2976,24 +2976,34 @@ static int ath10k_pci_probe(struct pci_dev *pdev, enum ath10k_hw_rev hw_rev; u32 chip_id; bool pci_ps; + int (*pci_soft_reset)(struct ath10k *ar); + int (*pci_hard_reset)(struct ath10k *ar); switch (pci_dev->device) { case QCA988X_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA988X; pci_ps = false; + pci_soft_reset = ath10k_pci_warm_reset; + pci_hard_reset = ath10k_pci_qca988x_chip_reset; break; case QCA6164_2_1_DEVICE_ID: case QCA6174_2_1_DEVICE_ID: hw_rev = ATH10K_HW_QCA6174; pci_ps = true; + pci_soft_reset = ath10k_pci_warm_reset; + pci_hard_reset = ath10k_pci_qca6174_chip_reset; break; case QCA99X0_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA99X0; pci_ps = false; + pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset; + pci_hard_reset = ath10k_pci_qca99x0_chip_reset; break; case QCA9377_1_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA9377; pci_ps = true; + pci_soft_reset = NULL; + pci_hard_reset = ath10k_pci_qca6174_chip_reset; break; default: WARN_ON(1); @@ -3018,6 +3028,8 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar->dev_id = pci_dev->device; ar_pci->pci_ps = pci_ps; ar_pci->bus_ops = _pci_bus_ops; + ar_pci->pci_soft_reset = pci_soft_reset; + ar_pci->pci_hard_reset = pci_hard_reset; ar->id.vendor = pdev->vendor; ar->id.device = pdev->device; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 959dc32..6eca1df 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -234,6 +234,12 @@ struct ath10k_pci { const struct ath10k_bus_ops *bus_ops; + /* Chip specific pci reset routine used to do a safe reset */ + int (*pci_soft_reset)(struct ath10k *ar); + + /* Chip specific pci full reset function */ + int (*pci_hard_reset)(struct ath10k *ar); + /* Keep this entry in the last, memory for struct ath10k_ahb is * allocated (ahb support enabled case) in the continuation of * this struct. -- 1.9
[PATCH 1/4] ath10k: Move rx_location_info out of struct rx_pkt_end
Define rx_location_info in struct rx_ppdu_end_qca99x0 after rx_pkt_end. This is to prepare rx_ppdu_end for QCA9984 chip. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/rx_desc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h index ca8d168..3e7dfaa 100644 --- a/drivers/net/wireless/ath/ath10k/rx_desc.h +++ b/drivers/net/wireless/ath/ath10k/rx_desc.h @@ -994,7 +994,6 @@ struct rx_pkt_end { __le32 info0; /* %RX_PKT_END_INFO0_ */ __le32 phy_timestamp_1; __le32 phy_timestamp_2; - __le32 rx_location_info; /* %RX_LOCATION_INFO_ */ } __packed; enum rx_phy_ppdu_end_info0 { @@ -1067,6 +1066,7 @@ struct rx_phy_ppdu_end { struct rx_ppdu_end_qca99x0 { struct rx_pkt_end rx_pkt_end; + __le32 rx_location_info; /* %RX_LOCATION_INFO_ */ struct rx_phy_ppdu_end rx_phy_ppdu_end; __le32 rx_timing_offset; /* %RX_PPDU_END_RX_TIMING_OFFSET_ */ __le32 rx_info; /* %RX_PPDU_END_RX_INFO_ */ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/4] Add support for QCA9984
This patch set adds QCA9984/QCA9994 1.0 support. Boot sequence is same as QCA99X0. Vasanthakumar Thiagarajan (4): ath10k: Move rx_location_info out of struct rx_pkt_end ath10k: Clean up growing hw checks during safe and full reset ath10k: Define rx_ppdu_end for QCA9984 ath10k: Enable support for QCA9984 drivers/net/wireless/ath/ath10k/core.c| 23 drivers/net/wireless/ath/ath10k/hw.h | 11 ++ drivers/net/wireless/ath/ath10k/pci.c | 58 ++- drivers/net/wireless/ath/ath10k/pci.h | 6 drivers/net/wireless/ath/ath10k/rx_desc.h | 48 - 5 files changed, 129 insertions(+), 17 deletions(-) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ath10k: Advertise force AP scan feature
Results obtained from scan can be used for spectrum management by doing something like building information of preferred channel lists and sharing them with stations around. It is to be noted that traffic to the connected stations would be affected during the scan. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ebff9c0..48b789c 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -7697,7 +7697,8 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->wiphy->max_remain_on_channel_duration = 5000; ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; - ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; + ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | + NL80211_FEATURE_AP_SCAN; ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] mac80211: Allow probe response frame rx to user space in AP mode
Especially during off-channel scan user space might be interested in probe reponse frames along with beacon to build a list of preferred channel and bssid which could be sent to the stations around for better spectrum management. Do not drop probe response frame in AP mode and advertise driver's capability to receive probe response frame in AP mode to user space. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- net/mac80211/main.c | 2 ++ net/mac80211/rx.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 8190bf2..c8a97da 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -401,6 +401,7 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4) | BIT(IEEE80211_STYPE_DISASSOC >> 4) | BIT(IEEE80211_STYPE_AUTH >> 4) | BIT(IEEE80211_STYPE_DEAUTH >> 4) | @@ -412,6 +413,7 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4) | BIT(IEEE80211_STYPE_DISASSOC >> 4) | BIT(IEEE80211_STYPE_AUTH >> 4) | BIT(IEEE80211_STYPE_DEAUTH >> 4) | diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9127957..9d8f8ea 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3464,6 +3464,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) return false; if (ieee80211_is_public_action(hdr, skb->len)) return true; + if (ieee80211_is_probe_resp(hdr->frame_control)) + return true; return ieee80211_is_beacon(hdr->frame_control); } -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V2 0/3] Fix few WMI/HTT interfaces
On Thursday 05 November 2015 04:33 PM, Kalle Valo wrote: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> writes: On Wed, Nov 04, 2015 at 07:59:39PM +0200, Kalle Valo wrote: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> writes: This patch set fixes mismatch in peer_assoc complete wmi command for version 10.4 and peer_id configuration for HTT version < 3.4. V2: - Add cover letter - Rename ath10k_mac_need_offchan_tx_work() to ath10k_mac_tx_frm_has_freq(). Add htt-op-version check to the helper and use it in ath10k_htt_tx() while configuring peerid. Vasanthakumar Thiagarajan (3): ath10k: Fix peer assoc complete WMI command for 10.4 ath10k: Rename the helper which is used for off-channel tx ath10k: Fix peerid configuration in htt tx desc for htt version < 3.4 These had a conflict but you didn't use ath.git as the baseline so I can't easily fix them. Please try always to use clean ath.git master branch as the baseline for your patches. Applying: ath10k: Fix peer assoc complete WMI command for 10.4 fatal: sha1 information is lacking or useless (drivers/net/wireless/ath/ath10k/wmi.h). Repository lacks necessary blobs to fall back on 3-way merge. Cannot fall back to three-way merge. Patch failed at 0001 ath10k: Fix peer assoc complete WMI command for 10.4 Sorry for this. I prepared these patches on ath:master on top of my other pending patch set. Not sure what went wrong. If you have two patchsets you shouldn't have them on the same branch, unless they have a strict dependency with each other of course. I prefer that you have two separate topic branches which both use the master branch as the baseline as then it's easiest for me to handle conflicts etc. Sure, thanks. Vasanth -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V3 3/3] ath10k: Fix peerid configuration in htt tx desc for htt version < 3.4
Of a word in struct htt_data_tx_desc htt version >= 3.4 firmware uses LSB 16-bit for frequency configuration which is used for offchannel tx and MSB 16-bit is for peerid. But other firmwares using version 2.X (10.1, 10.2.2, 10.2.4 and 10.4) are using 32-bit for peerid in htt tx desc. So far no issue is found with the existing code setting peerid and freq for HTT version 2.X, this could be mainly because of 0 as frequecy (home channel) is being always passed with those firmwares. There may be issues when non-zero freq is passed with firmware using < 3.4 htt version. To be safe use target_version_major and target_version_minor along with htt-op-version before configuring peer id and freq in htt tx desc. This patch extends ath10k_mac_tx_frm_has_freq() to check for htt_op_version_tlv and uses the helper while setting peerid in htt_tx_desc. Fixes: 8d6d36243610 ("ath10k: fix offchan reliability") Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/htt.h| 9 +++-- drivers/net/wireless/ath/ath10k/htt_tx.c | 11 +-- drivers/net/wireless/ath/ath10k/mac.c| 5 +++-- drivers/net/wireless/ath/ath10k/mac.h| 1 + 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 74ccfb29..2b87ed6 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -166,8 +166,13 @@ struct htt_data_tx_desc { __le16 len; __le16 id; __le32 frags_paddr; - __le16 peerid; - __le16 freq; + union { + __le32 peerid; + struct { + __le16 peerid; + __le16 freq; + } __packed offchan_tx; + } __packed; u8 prefetch[0]; /* start of frame, for FW classification engine */ } __packed; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index bd8f264..8f76b9d 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -688,8 +688,15 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len); skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id); skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); - skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID); - skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq); + if (ath10k_mac_tx_frm_has_freq(ar)) { + skb_cb->htt.txbuf->cmd_tx.offchan_tx.peerid = + __cpu_to_le16(HTT_INVALID_PEERID); + skb_cb->htt.txbuf->cmd_tx.offchan_tx.freq = + __cpu_to_le16(skb_cb->htt.freq); + } else { + skb_cb->htt.txbuf->cmd_tx.peerid = + __cpu_to_le32(HTT_INVALID_PEERID); + } trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid); ath10k_dbg(ar, ATH10K_DBG_HTT, diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 363a99c..76484a9 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3287,7 +3287,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, } } -static bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) +bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) { /* FIXME: Not really sure since when the behaviour changed. At some * point new firmware stopped requiring creation of peer entries for @@ -3296,7 +3296,8 @@ static bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) * because that's when the `freq` was introduced to TX_FRM HTT command. */ return (ar->htt.target_version_major >= 3 && - ar->htt.target_version_minor >= 4); + ar->htt.target_version_minor >= 4 && + ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV); } static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index e3cefe4..f504804 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -74,6 +74,7 @@ void ath10k_mac_tx_lock(struct ath10k *ar, int reason); void ath10k_mac_tx_unlock(struct ath10k *ar, int reason); void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason); void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason); +bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar); static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) { -- 1.9.1 -- To unsubscribe from this list: send the line "unsu
[PATCH V3 0/3] Fix few WMI/HTT interfaces
This patch set fixes mismatch in peer_assoc complete wmi command for version 10.4 and peer_id configuration for HTT version < 3.4. V2: - Add cover letter - Rename ath10k_mac_need_offchan_tx_work() to ath10k_mac_tx_frm_has_freq(). Add htt-op-version check to the helper and use it in ath10k_htt_tx() while configuring peerid. V3: - Rebase on top of ath:master TOT Vasanthakumar Thiagarajan (3): ath10k: Fix peer assoc complete WMI command for 10.4 ath10k: Rename the helper which is used for off-channel tx ath10k: Fix peerid configuration in htt tx desc for htt version < 3.4 drivers/net/wireless/ath/ath10k/htt.h| 9 ++-- drivers/net/wireless/ath/ath10k/htt_tx.c | 11 -- drivers/net/wireless/ath/ath10k/mac.c| 9 drivers/net/wireless/ath/ath10k/mac.h| 1 + drivers/net/wireless/ath/ath10k/wmi.c| 37 +++- drivers/net/wireless/ath/ath10k/wmi.h| 5 + 6 files changed, 63 insertions(+), 9 deletions(-) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V3 2/3] ath10k: Rename the helper which is used for off-channel tx
Rename ath10k_mac_need_offchan_tx_work() to ath10k_mac_tx_frm_has_freq() to make it more meaningful. This helper will be used in the future change. No functionality change. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/mac.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index a53e213..363a99c 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3287,7 +3287,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, } } -static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar) +static bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) { /* FIXME: Not really sure since when the behaviour changed. At some * point new firmware stopped requiring creation of peer entries for @@ -3295,8 +3295,8 @@ static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar) * tx credit replenishment and reliability). Assuming it's at least 3.4 * because that's when the `freq` was introduced to TX_FRM HTT command. */ - return !(ar->htt.target_version_major >= 3 && -ar->htt.target_version_minor >= 4); + return (ar->htt.target_version_major >= 3 && + ar->htt.target_version_minor >= 4); } static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) @@ -3680,7 +3680,7 @@ static void ath10k_tx(struct ieee80211_hw *hw, ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id; spin_unlock_bh(>data_lock); - if (ath10k_mac_need_offchan_tx_work(ar)) { + if (!ath10k_mac_tx_frm_has_freq(ar)) { ATH10K_SKB_CB(skb)->htt.freq = 0; ATH10K_SKB_CB(skb)->htt.is_offchan = true; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V3 1/3] ath10k: Fix peer assoc complete WMI command for 10.4
There is an extra 4-byte member when compared to WMI 10.2 added to assoc complete command in WMI 10.4. This new member is used for 160Mhz related configuration. This WMI command mismatch between host and firmware does not cause any real issues because this new member is not used in 10.4 firmwares so far (10.4.1.00030-1). This difference in WMI command interface brings in a new wmi_ops for 10.4 gen_peer_assoc(). No noticeable functionality differences with this change can be seen with the current 10.4 firmwares, but the WMI interface has to be fixed to work with future 10.4 firmwares which may be using this new member. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/wmi.c | 37 ++- drivers/net/wireless/ath/ath10k/wmi.h | 5 + 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 56806d9..9021079 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -6376,6 +6376,16 @@ ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf, cmd->info0 = __cpu_to_le32(info0); } +static void +ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf, + const struct wmi_peer_assoc_complete_arg *arg) +{ + struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf; + + ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg); + cmd->peer_bw_rxnss_override = 0; +} + static int ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg) { @@ -6465,6 +6475,31 @@ ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar, } static struct sk_buff * +ath10k_wmi_10_4_op_gen_peer_assoc(struct ath10k *ar, + const struct wmi_peer_assoc_complete_arg *arg) +{ + size_t len = sizeof(struct wmi_10_4_peer_assoc_complete_cmd); + struct sk_buff *skb; + int ret; + + ret = ath10k_wmi_peer_assoc_check_arg(arg); + if (ret) + return ERR_PTR(ret); + + skb = ath10k_wmi_alloc_skb(ar, len); + if (!skb) + return ERR_PTR(-ENOMEM); + + ath10k_wmi_peer_assoc_fill_10_4(ar, skb->data, arg); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi peer assoc vdev %d addr %pM (%s)\n", + arg->vdev_id, arg->addr, + arg->peer_reassoc ? "reassociate" : "new"); + return skb; +} + +static struct sk_buff * ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar) { struct sk_buff *skb; @@ -7584,6 +7619,7 @@ static const struct wmi_ops wmi_10_4_ops = { .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, .gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param, + .gen_peer_assoc = ath10k_wmi_10_4_op_gen_peer_assoc, .gen_set_psmode = ath10k_wmi_op_gen_set_psmode, .gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps, .gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps, @@ -7603,7 +7639,6 @@ static const struct wmi_ops wmi_10_4_ops = { .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill, /* shared with 10.2 */ - .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, .gen_request_stats = ath10k_wmi_op_gen_request_stats, .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature, }; diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index a35c91e..80d3f1c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -5799,6 +5799,11 @@ struct wmi_10_2_peer_assoc_complete_cmd { __le32 info0; /* WMI_PEER_ASSOC_INFO0_ */ } __packed; +struct wmi_10_4_peer_assoc_complete_cmd { + struct wmi_10_2_peer_assoc_complete_cmd cmd; + __le32 peer_bw_rxnss_override; +} __packed; + struct wmi_peer_assoc_complete_arg { u8 addr[ETH_ALEN]; u32 vdev_id; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V2 0/3] Fix few WMI/HTT interfaces
On Wed, Nov 04, 2015 at 07:59:39PM +0200, Kalle Valo wrote: > Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> writes: > > > This patch set fixes mismatch in peer_assoc complete wmi command for > > version 10.4 and peer_id configuration for HTT version < 3.4. > > > > V2: > > - Add cover letter > > - Rename ath10k_mac_need_offchan_tx_work() to > > ath10k_mac_tx_frm_has_freq(). Add htt-op-version check > > to the helper and use it in ath10k_htt_tx() while configuring > > peerid. > > > > Vasanthakumar Thiagarajan (3): > > ath10k: Fix peer assoc complete WMI command for 10.4 > > ath10k: Rename the helper which is used for off-channel tx > > ath10k: Fix peerid configuration in htt tx desc for htt version < 3.4 > > These had a conflict but you didn't use ath.git as the baseline so I > can't easily fix them. Please try always to use clean ath.git master > branch as the baseline for your patches. > > Applying: ath10k: Fix peer assoc complete WMI command for 10.4 > fatal: sha1 information is lacking or useless > (drivers/net/wireless/ath/ath10k/wmi.h). > Repository lacks necessary blobs to fall back on 3-way merge. > Cannot fall back to three-way merge. > Patch failed at 0001 ath10k: Fix peer assoc complete WMI command for 10.4 Sorry for this. I prepared these patches on ath:master on top of my other pending patch set. Not sure what went wrong. Ill resend this. Thanks. Vasanth -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 0/3] Fix few WMI/HTT interfaces
This patch set fixes mismatch in peer_assoc complete wmi command for version 10.4 and peer_id configuration for HTT version < 3.4. V2: - Add cover letter - Rename ath10k_mac_need_offchan_tx_work() to ath10k_mac_tx_frm_has_freq(). Add htt-op-version check to the helper and use it in ath10k_htt_tx() while configuring peerid. Vasanthakumar Thiagarajan (3): ath10k: Fix peer assoc complete WMI command for 10.4 ath10k: Rename the helper which is used for off-channel tx ath10k: Fix peerid configuration in htt tx desc for htt version < 3.4 drivers/net/wireless/ath/ath10k/htt.h| 9 ++-- drivers/net/wireless/ath/ath10k/htt_tx.c | 11 -- drivers/net/wireless/ath/ath10k/mac.c| 9 drivers/net/wireless/ath/ath10k/mac.h| 1 + drivers/net/wireless/ath/ath10k/wmi.c| 37 +++- drivers/net/wireless/ath/ath10k/wmi.h| 5 + 6 files changed, 63 insertions(+), 9 deletions(-) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 2/3] ath10k: Rename the helper which is used for off-channel tx
Rename ath10k_mac_need_offchan_tx_work() to ath10k_mac_tx_frm_has_freq() to make it more meaningful. This helper will be used in the future change. No functionality change. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/mac.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index a7411fe..f121021 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3280,7 +3280,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, } } -static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar) +static bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) { /* FIXME: Not really sure since when the behaviour changed. At some * point new firmware stopped requiring creation of peer entries for @@ -3288,8 +3288,8 @@ static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar) * tx credit replenishment and reliability). Assuming it's at least 3.4 * because that's when the `freq` was introduced to TX_FRM HTT command. */ - return !(ar->htt.target_version_major >= 3 && -ar->htt.target_version_minor >= 4); + return (ar->htt.target_version_major >= 3 && + ar->htt.target_version_minor >= 4); } static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) @@ -3673,7 +3673,7 @@ static void ath10k_tx(struct ieee80211_hw *hw, ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id; spin_unlock_bh(>data_lock); - if (ath10k_mac_need_offchan_tx_work(ar)) { + if (!ath10k_mac_tx_frm_has_freq(ar)) { ATH10K_SKB_CB(skb)->htt.freq = 0; ATH10K_SKB_CB(skb)->htt.is_offchan = true; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 3/3] ath10k: Fix peerid configuration in htt tx desc for htt version < 3.4
Of a word in struct htt_data_tx_desc htt version >= 3.4 firmware uses LSB 16-bit for frequency configuration which is used for offchannel tx and MSB 16-bit is for peerid. But other firmwares using version 2.X (10.1, 10.2.2, 10.2.4 and 10.4) are using 32-bit for peerid in htt tx desc. So far no issue is found with the existing code setting peerid and freq for HTT version 2.X, this could be mainly because of 0 as frequecy (home channel) is being always passed with those firmwares. There may be issues when non-zero freq is passed with firmware using < 3.4 htt version. To be safe use target_version_major and target_version_minor along with htt-op-version before configuring peer id and freq in htt tx desc. This patch extends ath10k_mac_tx_frm_has_freq() to check for htt_op_version_tlv and uses the helper while setting peerid in htt_tx_desc. Fixes: 8d6d36243610 ("ath10k: fix offchan reliability") Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/htt.h| 9 +++-- drivers/net/wireless/ath/ath10k/htt_tx.c | 11 +-- drivers/net/wireless/ath/ath10k/mac.c| 5 +++-- drivers/net/wireless/ath/ath10k/mac.h| 1 + 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 2bad50e..44fb4f2 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -166,8 +166,13 @@ struct htt_data_tx_desc { __le16 len; __le16 id; __le32 frags_paddr; - __le16 peerid; - __le16 freq; + union { + __le32 peerid; + struct { + __le16 peerid; + __le16 freq; + } __packed offchan_tx; + } __packed; u8 prefetch[0]; /* start of frame, for FW classification engine */ } __packed; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 1682397..2dcea48 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -681,8 +681,15 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len); skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id); skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); - skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID); - skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq); + if (ath10k_mac_tx_frm_has_freq(ar)) { + skb_cb->htt.txbuf->cmd_tx.offchan_tx.peerid = + __cpu_to_le16(HTT_INVALID_PEERID); + skb_cb->htt.txbuf->cmd_tx.offchan_tx.freq = + __cpu_to_le16(skb_cb->htt.freq); + } else { + skb_cb->htt.txbuf->cmd_tx.peerid = + __cpu_to_le32(HTT_INVALID_PEERID); + } trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid); ath10k_dbg(ar, ATH10K_DBG_HTT, diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index f121021..7fe51bf 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3280,7 +3280,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, } } -static bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) +bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) { /* FIXME: Not really sure since when the behaviour changed. At some * point new firmware stopped requiring creation of peer entries for @@ -3289,7 +3289,8 @@ static bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) * because that's when the `freq` was introduced to TX_FRM HTT command. */ return (ar->htt.target_version_major >= 3 && - ar->htt.target_version_minor >= 4); + ar->htt.target_version_minor >= 4 && + ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV); } static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index e3cefe4..f504804 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -74,6 +74,7 @@ void ath10k_mac_tx_lock(struct ath10k *ar, int reason); void ath10k_mac_tx_unlock(struct ath10k *ar, int reason); void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason); void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason); +bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar); static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) { -- 1.9.1 -- To unsubscribe from this list: send the line "unsu
[PATCH V2 1/3] ath10k: Fix peer assoc complete WMI command for 10.4
There is an extra 4-byte member when compared to WMI 10.2 added to assoc complete command in WMI 10.4. This new member is used for 160Mhz related configuration. This WMI command mismatch between host and firmware does not cause any real issues because this new member is not used in 10.4 firmwares so far (10.4.1.00030-1). This difference in WMI command interface brings in a new wmi_ops for 10.4 gen_peer_assoc(). No noticeable functionality differences with this change can be seen with the current 10.4 firmwares, but the WMI interface has to be fixed to work with future 10.4 firmwares which may be using this new member. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/wmi.c | 37 ++- drivers/net/wireless/ath/ath10k/wmi.h | 5 + 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 7569db0..e8614ab 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -6328,6 +6328,16 @@ ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf, cmd->info0 = __cpu_to_le32(info0); } +static void +ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf, + const struct wmi_peer_assoc_complete_arg *arg) +{ + struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf; + + ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg); + cmd->peer_bw_rxnss_override = 0; +} + static int ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg) { @@ -6417,6 +6427,31 @@ ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar, } static struct sk_buff * +ath10k_wmi_10_4_op_gen_peer_assoc(struct ath10k *ar, + const struct wmi_peer_assoc_complete_arg *arg) +{ + size_t len = sizeof(struct wmi_10_4_peer_assoc_complete_cmd); + struct sk_buff *skb; + int ret; + + ret = ath10k_wmi_peer_assoc_check_arg(arg); + if (ret) + return ERR_PTR(ret); + + skb = ath10k_wmi_alloc_skb(ar, len); + if (!skb) + return ERR_PTR(-ENOMEM); + + ath10k_wmi_peer_assoc_fill_10_4(ar, skb->data, arg); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi peer assoc vdev %d addr %pM (%s)\n", + arg->vdev_id, arg->addr, + arg->peer_reassoc ? "reassociate" : "new"); + return skb; +} + +static struct sk_buff * ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar) { struct sk_buff *skb; @@ -7536,6 +7571,7 @@ static const struct wmi_ops wmi_10_4_ops = { .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, .gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param, + .gen_peer_assoc = ath10k_wmi_10_4_op_gen_peer_assoc, .gen_set_psmode = ath10k_wmi_op_gen_set_psmode, .gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps, .gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps, @@ -7555,7 +7591,6 @@ static const struct wmi_ops wmi_10_4_ops = { .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill, /* shared with 10.2 */ - .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, .gen_request_stats = ath10k_wmi_op_gen_request_stats, }; diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index a8ea93e..ab6d218 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -5741,6 +5741,11 @@ struct wmi_10_2_peer_assoc_complete_cmd { __le32 info0; /* WMI_PEER_ASSOC_INFO0_ */ } __packed; +struct wmi_10_4_peer_assoc_complete_cmd { + struct wmi_10_2_peer_assoc_complete_cmd cmd; + __le32 peer_bw_rxnss_override; +} __packed; + struct wmi_peer_assoc_complete_arg { u8 addr[ETH_ALEN]; u32 vdev_id; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] ath10k: Fix peerid configuration in htt tx desc for htt version < 3.4
Of a word in struct htt_data_tx_desc htt version >= 3.4 firmware uses LSB 16-bit for frequency configuration which is used for offchannel tx and MSB 16-bit is for peerid. But other firmwares using version 2.X (10.1, 10.2.2, 10.2.4 and 10.4) are using 32-bit for peerid in htt tx desc. So far no issue is found with the existing code setting peerid and freq for HTT version 2.X, this could be mainly because of 0 as frequecy (home channel) is being always passed with those firmwares. There may be issues when non-zero freq is passed with firmware using < 3.4 htt version. To be safe use target_version_major and target_version_minor along with htt-op-version before configuring peer id and freq in htt tx desc. Fixes: 8d6d36243610 ("ath10k: fix offchan reliability") Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/htt.h| 9 +++-- drivers/net/wireless/ath/ath10k/htt_tx.c | 13 +++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 2bad50e..44fb4f2 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -166,8 +166,13 @@ struct htt_data_tx_desc { __le16 len; __le16 id; __le32 frags_paddr; - __le16 peerid; - __le16 freq; + union { + __le32 peerid; + struct { + __le16 peerid; + __le16 freq; + } __packed offchan_tx; + } __packed; u8 prefetch[0]; /* start of frame, for FW classification engine */ } __packed; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 1682397..bf19247 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -681,8 +681,17 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len); skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id); skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); - skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID); - skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq); + if (ar->htt.target_version_major >= 3 && + ar->htt.target_version_minor >= 4 && + ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV) { + skb_cb->htt.txbuf->cmd_tx.offchan_tx.peerid = + __cpu_to_le16(HTT_INVALID_PEERID); + skb_cb->htt.txbuf->cmd_tx.offchan_tx.freq = + __cpu_to_le16(skb_cb->htt.freq); + } else { + skb_cb->htt.txbuf->cmd_tx.peerid = + __cpu_to_le32(HTT_INVALID_PEERID); + } trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid); ath10k_dbg(ar, ATH10K_DBG_HTT, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] ath10k: Fix peer assoc complete WMI command for 10.4
There is an extra 4-byte member when compared to WMI 10.2 added to assoc complete command in WMI 10.4. This new member is used for 160Mhz related configuration. This WMI command mismatch between host and firmware does not cause any real issues because this new member is not used in 10.4 firmwares so far (10.4.1.00030-1). This difference in WMI command interface brings in a new wmi_ops for 10.4 gen_peer_assoc(). No noticeable functionality differences with this change can be seen with the current 10.4 firmwares, but the WMI interface has to be fixed to work with future 10.4 firmwares which may be using this new member. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/wmi.c | 37 ++- drivers/net/wireless/ath/ath10k/wmi.h | 5 + 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 7569db0..e8614ab 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -6328,6 +6328,16 @@ ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf, cmd->info0 = __cpu_to_le32(info0); } +static void +ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf, + const struct wmi_peer_assoc_complete_arg *arg) +{ + struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf; + + ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg); + cmd->peer_bw_rxnss_override = 0; +} + static int ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg) { @@ -6417,6 +6427,31 @@ ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar, } static struct sk_buff * +ath10k_wmi_10_4_op_gen_peer_assoc(struct ath10k *ar, + const struct wmi_peer_assoc_complete_arg *arg) +{ + size_t len = sizeof(struct wmi_10_4_peer_assoc_complete_cmd); + struct sk_buff *skb; + int ret; + + ret = ath10k_wmi_peer_assoc_check_arg(arg); + if (ret) + return ERR_PTR(ret); + + skb = ath10k_wmi_alloc_skb(ar, len); + if (!skb) + return ERR_PTR(-ENOMEM); + + ath10k_wmi_peer_assoc_fill_10_4(ar, skb->data, arg); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi peer assoc vdev %d addr %pM (%s)\n", + arg->vdev_id, arg->addr, + arg->peer_reassoc ? "reassociate" : "new"); + return skb; +} + +static struct sk_buff * ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar) { struct sk_buff *skb; @@ -7536,6 +7571,7 @@ static const struct wmi_ops wmi_10_4_ops = { .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, .gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param, + .gen_peer_assoc = ath10k_wmi_10_4_op_gen_peer_assoc, .gen_set_psmode = ath10k_wmi_op_gen_set_psmode, .gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps, .gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps, @@ -7555,7 +7591,6 @@ static const struct wmi_ops wmi_10_4_ops = { .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill, /* shared with 10.2 */ - .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, .gen_request_stats = ath10k_wmi_op_gen_request_stats, }; diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index a8ea93e..ab6d218 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -5741,6 +5741,11 @@ struct wmi_10_2_peer_assoc_complete_cmd { __le32 info0; /* WMI_PEER_ASSOC_INFO0_ */ } __packed; +struct wmi_10_4_peer_assoc_complete_cmd { + struct wmi_10_2_peer_assoc_complete_cmd cmd; + __le32 peer_bw_rxnss_override; +} __packed; + struct wmi_peer_assoc_complete_arg { u8 addr[ETH_ALEN]; u32 vdev_id; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] ath10k: Fix peerid configuration in htt tx desc for htt version < 3.4
On Monday 02 November 2015 03:57 PM, Michal Kazior wrote: On 2 November 2015 at 09:33, Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> wrote: Of a word in struct htt_data_tx_desc htt version >= 3.4 firmware uses LSB 16-bit for frequency configuration which is used for offchannel tx and MSB 16-bit is for peerid. But other firmwares using version 2.X (10.1, 10.2.2, 10.2.4 and 10.4) are using 32-bit for peerid in htt tx desc. So far no issue is found with the existing code setting peerid and freq for HTT version 2.X, this could be mainly because of 0 as frequecy (home channel) is being always passed with those firmwares. There may be issues when non-zero freq is passed with firmware using < 3.4 htt version. To be safe use target_version_major and target_version_minor along with htt-op-version before configuring peer id and freq in htt tx desc. Fixes: 8d6d36243610 ("ath10k: fix offchan reliability") Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/htt.h| 9 +++-- drivers/net/wireless/ath/ath10k/htt_tx.c | 13 +++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 2bad50e..44fb4f2 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -166,8 +166,13 @@ struct htt_data_tx_desc { __le16 len; __le16 id; __le32 frags_paddr; - __le16 peerid; - __le16 freq; + union { + __le32 peerid; + struct { + __le16 peerid; + __le16 freq; + } __packed offchan_tx; + } __packed; u8 prefetch[0]; /* start of frame, for FW classification engine */ } __packed; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 1682397..bf19247 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -681,8 +681,17 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len); skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id); skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); - skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID); - skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq); + if (ar->htt.target_version_major >= 3 && + ar->htt.target_version_minor >= 4 && + ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV) { Hmm.. I think it'd be better to rename ath10k_mac_need_offchan_tx_work() to, e.g. ath10k_htt_tx_frm_has_freq() and add the htt.op_version check to it. Sure, thanks. Vasanth -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] ath10k: Add new service defines for 10.4
No functional changes, adds new wmi service bits for 10.4 firmware to be sync with 10.4 firmware. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/wmi.h | 10 ++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index cec887a..103dd8c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -175,6 +175,8 @@ enum wmi_service { WMI_SERVICE_AUX_SPECTRAL_INTF, WMI_SERVICE_AUX_CHAN_LOAD_INTF, WMI_SERVICE_BSS_CHANNEL_INFO_64, + WMI_SERVICE_EXT_RES_CFG_SUPPORT, + WMI_SERVICE_MESH, /* keep last */ WMI_SERVICE_MAX, @@ -286,6 +288,8 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_AUX_SPECTRAL_INTF, WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF, WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, + WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, + WMI_10_4_SERVICE_MESH, }; static inline char *wmi_service_name(int service_id) @@ -375,6 +379,8 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_AUX_SPECTRAL_INTF); SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF); SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64); + SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT); + SVCSTR(WMI_SERVICE_MESH); default: return NULL; } @@ -600,6 +606,10 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_AUX_CHAN_LOAD_INTF, len); SVCMAP(WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, WMI_SERVICE_BSS_CHANNEL_INFO_64, len); + SVCMAP(WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, + WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); + SVCMAP(WMI_10_4_SERVICE_MESH, + WMI_SERVICE_MESH, len); } #undef SVCMAP -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/3] Add new WMI defines to 10.4
This patch set does not have any real functionality changes. Adds new WMI defines to be in sync with 10.4 firmware. Vasanthakumar Thiagarajan (3): ath10k: Add new service defines for 10.4 ath10k: Add new WMI cmd/event defines for 10.4 ath10k: Add new pdev params defines to 10.4 drivers/net/wireless/ath/ath10k/wmi.h | 20 1 file changed, 20 insertions(+) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] ath10k: Add new pdev params defines to 10.4
No functionality change, just sync to the latest pdev params that 10.4 firmware defines. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/wmi.h | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 3076581..a9073b0 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -3660,6 +3660,12 @@ enum wmi_10_4_pdev_param { WMI_10_4_PDEV_PARAM_WAPI_MBSSID_OFFSET, WMI_10_4_PDEV_PARAM_ARP_SRCADDR, WMI_10_4_PDEV_PARAM_ARP_DSTADDR, + WMI_10_4_PDEV_PARAM_TXPOWER_DECR_DB, + WMI_10_4_PDEV_PARAM_RX_BATCHMODE, + WMI_10_4_PDEV_PARAM_PACKET_AGGR_DELAY, + WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCH, + WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCALING_FACTOR, + WMI_10_4_PDEV_PARAM_CUST_TXPOWER_SCALE, }; struct wmi_pdev_set_param_cmd { -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] ath10k: Add new WMI cmd/event defines for 10.4
No real functionality change, add WMI command/event defines to be in sync with 10.4 firmware. Signed-off-by: Vasanthakumar Thiagarajan <vthia...@qti.qualcomm.com> --- drivers/net/wireless/ath/ath10k/wmi.h | 4 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 103dd8c..3076581 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -1582,6 +1582,9 @@ enum wmi_10_4_cmd_id { WMI_10_4_MU_CAL_START_CMDID, WMI_10_4_SET_CCA_PARAMS_CMDID, WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID, + WMI_10_4_EXT_RESOURCE_CFG_CMDID, + WMI_10_4_VDEV_SET_IE_CMDID, + WMI_10_4_SET_LTEU_CONFIG_CMDID, WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1, }; @@ -1644,6 +1647,7 @@ enum wmi_10_4_event_id { WMI_10_4_PDEV_TEMPERATURE_EVENTID, WMI_10_4_PDEV_NFCAL_POWER_ALL_CHANNELS_EVENTID, WMI_10_4_PDEV_BSS_CHAN_INFO_EVENTID, + WMI_10_4_MU_REPORT_EVENTID, WMI_10_4_PDEV_UTF_EVENTID = WMI_10_4_END_EVENTID - 1, }; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ath10k: Fix DMA alloc failure for target requested memory chunks
During long hours of stress testing like AP interface up/down along with continuous ping flood from a station doing connect/disconnect, it is observed that the system is not able to allocate DMA consistent memory of size 512KB chunks as requested by firmware in WMI_SERVICE_EVENTID. With the system memory getting fragmented during the run based on the size of the memory requested, the failure to return physically continguous memory of high order can happen. Once the system gets to this situation, bringing up the wifi interface will fail and a system reboot may be needed to make it work again. This problem is obseved with QCA99X0. To fix this issue, allocate the DMA memory requested by firmware during device probe time and keep it during the life time of the device. WMI service ready event handler is changed to allocate the memory chunks if it is not already allocated or if the memory allocated for the previous ready event is not same as the current requested ones. After this patch the memory usage when wifi is inactive will be inceased by few 100KB to 3MB based on the target type. Failure happens with the following stack trace [29557.488773] kworker/u4:1: page allocation failure: order:8, mode:0xd0 [29557.494297] CPU: 0 PID: 8402 Comm: kworker/u4:1 Not tainted 3.14.43 #7 [29557.500793] Workqueue: ath10k_aux_wq ath10k_wmi_event_service_ready_work [ath10k_core] [29557.508602] [c021e9b0] (unwind_backtrace) from [c021ba90] (show_stack+0x10/0x14) [29557.516580] [c021ba90] (show_stack) from [c03bdddc] (dump_stack+0x88/0xcc) [29557.523612] [c03bdddc] (dump_stack) from [c0290e34] (warn_alloc_failed+0xdc/0x108) [29557.531515] [c0290e34] (warn_alloc_failed) from [c0292d88] (__alloc_pages_nodemask+0x4f0/0x654) [29557.540485] [c0292d88] (__alloc_pages_nodemask) from [c0222b48] (__dma_alloc_buffer.isra.20+0x2c/0x104) [29557.550260] [c0222b48] (__dma_alloc_buffer.isra.20) from [c0222c34] (__alloc_remap_buffer.isra.23+0x14/0xb8) [29557.560413] [c0222c34] (__alloc_remap_buffer.isra.23) from [c022305c] (__dma_alloc+0x224/0x2b8) [29557.569490] [c022305c] (__dma_alloc) from [c0223208] (arm_dma_alloc+0x84/0x90) [29557.577010] [c0223208] (arm_dma_alloc) from [bf5159d0] (ath10k_wmi_event_service_ready_work+0x2f8/0x420 [ath10k_core]) [29557.588055] [bf5159d0] (ath10k_wmi_event_service_ready_work [ath10k_core]) from [c024260c] (process_one_work+0x20c/0x328) [29557.599305] [c024260c] (process_one_work) from [c02432d0] (worker_thread+0x228/0x360) [29557.607470] [c02432d0] (worker_thread) from [c0247f88] (kthread+0xd8/0xec) [29557.614750] [c0247f88] (kthread) from [c0208d18] (ret_from_fork+0x14/0x3c) [29557.712751] Normal: 696*4kB (UEMR) 512*8kB (UEMR) 367*16kB (UEMR) 404*32kB (UEMR) 455*64kB (UEMR) 424*128kB (UEMR) 379*256kB (UMR) 327*512kB (UMR) 1*1024kB (R) 0*2048kB 0*4096kB = 374544kB Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/core.c | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 76 +++--- drivers/net/wireless/ath/ath10k/wmi.h | 1 + 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b87b986..6e5aeed 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1714,6 +1714,7 @@ void ath10k_core_destroy(struct ath10k *ar) destroy_workqueue(ar-workqueue_aux); ath10k_debug_destroy(ar); + ath10k_wmi_free_host_mem(ar); ath10k_mac_destroy(ar); } EXPORT_SYMBOL(ath10k_core_destroy); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index ce01107..87d9de2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3917,6 +3917,53 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, return 0; } +static bool +ath10k_wmi_is_host_mem_allocated(struct ath10k *ar, +const struct wlan_host_mem_req **mem_reqs, +u32 num_mem_reqs) +{ + u32 req_id, num_units, unit_size, num_unit_info; + u32 pool_size; + int i, j; + bool found; + + if (ar-wmi.num_mem_chunks != num_mem_reqs) + return false; + + for (i = 0; i num_mem_reqs; ++i) { + req_id = __le32_to_cpu(mem_reqs[i]-req_id); + num_units = __le32_to_cpu(mem_reqs[i]-num_units); + unit_size = __le32_to_cpu(mem_reqs[i]-unit_size); + num_unit_info = __le32_to_cpu(mem_reqs[i]-num_unit_info); + + if (num_unit_info NUM_UNITS_IS_NUM_ACTIVE_PEERS) { + if (ar-num_active_peers) + num_units = ar-num_active_peers + 1; + else + num_units = ar-max_num_peers + 1; + } else if (num_unit_info NUM_UNITS_IS_NUM_PEERS
[PATCH] ath10k: Fill in wmi 10.4 command handlers for addba/delba debug commands
WMI 10.4 uses the same command interface as QCA988X for addba/delba debug wmi commands. Fill wmi_10_4_ops table with the functions used for QCA988X for these commands. With this change, the following debugfs entries can be used to configure the aggregation mode and to send addba request, addba response and delba respectively in manual aggregation mode for QCA99X0 chip. /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/XX:XX:XX:XX:XX:XX/aggr_mode /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/XX:XX:XX:XX:XX:XX/addba /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/XX:XX:XX:XX:XX:XX/addba_resp /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/XX:XX:XX:XX:XX:XX/delba Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/wmi.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 36b8f71..9769936 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -6482,6 +6482,10 @@ static const struct wmi_ops wmi_10_4_ops = { .gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable, .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable, .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode, + .gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp, + .gen_addba_send = ath10k_wmi_op_gen_addba_send, + .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, + .gen_delba_send = ath10k_wmi_op_gen_delba_send, /* shared with 10.2 */ .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] ath10k: Fix invalid survey reporting for QCA99X0
There are three WMI_CHAN_INFO events reported per channel in QCA99X0 firmware. First one is a notification at the begining of the channel dwell time with cmd_flag as CHAN_INFO_START(cmd_flag = 0), second one is a notification at the end of the dwell time with cmd_flag CHAN_INFO_PRE_COMPLETE (cmd_flag = 2) and the third is the indication with CHAN_INFO_COMPLETE (cmd_flag = 1) which is the last indication for the channel. Since there is a new state before the completion, the handler is to fixed so that the counts are deducted from the ones reported with CHAN_INFO_START rather than the ones reported with CHAN_INFO_PRE_COMPLETE. Without this fix there will be lots of 0 msecs reported as active and busy time. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/wmi.c | 6 -- drivers/net/wireless/ath/ath10k/wmi.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index e6d6b42..38e22e0 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2412,8 +2412,10 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb) ar-ch_info_can_report_survey = true; } - ar-survey_last_rx_clear_count = rx_clear_count; - ar-survey_last_cycle_count = cycle_count; + if (!(cmd_flags WMI_CHAN_INFO_FLAG_PRE_COMPLETE)) { + ar-survey_last_rx_clear_count = rx_clear_count; + ar-survey_last_cycle_count = cycle_count; + } exit: spin_unlock_bh(ar-data_lock); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 0d4efc9..5825c5c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -5585,6 +5585,7 @@ struct wmi_peer_sta_kickout_event { } __packed; #define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0) +#define WMI_CHAN_INFO_FLAG_PRE_COMPLETE BIT(1) /* Beacon filter wmi command info */ #define BCN_FLT_MAX_SUPPORTED_IES 256 -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] ath10k: Add cycle/rx_clear counters frequency to hw_params
The frequency at which cycle/rx_clear counters are running might change from one target type to another. QCA99X0 is running the counters at 150Mhz while QCA9888X and QCA6174 are running at 88Mhz. Add a new entry to hw_params to store the target specific frequency and use it in msecs conversion. This change fixes inconsistent channel active/busy time. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/core.c | 5 + drivers/net/wireless/ath/ath10k/core.h | 2 ++ drivers/net/wireless/ath/ath10k/hw.c | 4 ++-- drivers/net/wireless/ath/ath10k/hw.h | 3 +-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 2551067..2efd4e4 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -53,6 +53,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .uart_pin = 7, .has_shifted_cc_wraparound = true, .otp_exe_param = 0, + .channel_counters_freq_hz = 88000, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, .fw = QCA988X_HW_2_0_FW_FILE, @@ -68,6 +69,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR, .uart_pin = 6, .otp_exe_param = 0, + .channel_counters_freq_hz = 88000, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, .fw = QCA6174_HW_2_1_FW_FILE, @@ -83,6 +85,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, .uart_pin = 6, .otp_exe_param = 0, + .channel_counters_freq_hz = 88000, .fw = { .dir = QCA6174_HW_3_0_FW_DIR, .fw = QCA6174_HW_3_0_FW_FILE, @@ -98,6 +101,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, .uart_pin = 6, .otp_exe_param = 0, + .channel_counters_freq_hz = 88000, .fw = { /* uses same binaries as hw3.0 */ .dir = QCA6174_HW_3_0_FW_DIR, @@ -115,6 +119,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .uart_pin = 7, .otp_exe_param = 0x0700, .continuous_frag_desc = true, + .channel_counters_freq_hz = 15, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, .fw = QCA99X0_HW_2_0_FW_FILE, diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 6a387ba..862f6d0 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -609,6 +609,8 @@ struct ath10k { */ bool continuous_frag_desc; + u32 channel_counters_freq_hz; + struct ath10k_hw_params_fw { const char *dir; const char *fw; diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index fef7ccf..7b84d08 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -152,6 +152,6 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, cc -= cc_prev - cc_fix; rcc -= rcc_prev; - survey-time = CCNT_TO_MSEC(cc); - survey-time_busy = CCNT_TO_MSEC(rcc); + survey-time = CCNT_TO_MSEC(ar, cc); + survey-time_busy = CCNT_TO_MSEC(ar, rcc); } diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index d9de4a7..23afcda 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -552,8 +552,7 @@ enum ath10k_hw_rate_cck { #define SCRATCH_3_ADDRESS ar-regs-scratch_3_address #define CPU_INTR_ADDRESS 0x0010 -/* Cycle counters are running at 88MHz */ -#define CCNT_TO_MSEC(x) ((x) / 88000) +#define CCNT_TO_MSEC(ar, x) ((x) / ar-hw_params.channel_counters_freq_hz) /* Firmware indications to the Host via SCRATCH_3 register. */ #define FW_INDICATOR_ADDRESS ar-regs-fw_indicator_address -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] ath10k: Add QCA99X0 to supported device list
On Wednesday 05 August 2015 05:51 PM, Felix Fietkau wrote: On 2015-07-21 13:36, Vasanthakumar Thiagarajan wrote: Add vendor/device id of QCA99X0 V2.0 to pci id table and QCA99X0_HW_2_0_CHIP_ID_REV to ath10k_pci_supp_chips[] for QCA99X0 to get detected by the driver. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com I just tested a 99X0 card, and I'm getting this: [8.742514] ath10k_pci :01:00.0: enabling device (0140 - 0142) [8.747173] ath10k_pci :01:00.0: pci irq msi interrupts 1 irq_mode 0 reset_mode 0 [ 11.793314] ath10k_pci :01:00.0: failed to receive initialized event from target: [ 11.793344] ath10k_pci :01:00.0: failed to wait for target after cold reset: -110 [ 11.800814] ath10k_pci :01:00.0: failed to reset chip: -110 [ 11.809228] ath10k_pci: probe of :01:00.0 failed with error -110 This is on an AP148 board with Linux 3.18, backports generated from latest wireless-testing (2015-08-03) + all patches from kvalo's ath tree. Any idea about the version of AP148 that you are using?. By any chance did you check if QCA988X is working on the same board?. Vasanth -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] ath10k: remove NULL ptr deref in variable init of ath10k_monitor_vdev_start
On Tuesday 28 July 2015 12:52 AM, John W. Linville wrote: In ath10k_monitor_vdev_start, chandef is initialized to NULL and then channel is immediately thereafter initialized to chandef-chan (i.e. NULL-chan). This appears to be some sort of cut-n-paste error, since the same assignment is done later (i.e. after chandef has been properly assigned to a non-NULL value). So, let's just remove this brown paper bag typo/thinko... :-) Coverity CID #1309505 Signed-off-by: John W. Linville linvi...@tuxdriver.com --- drivers/net/wireless/ath/ath10k/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index c9a7d5b5dffc..2823222dea92 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -836,7 +836,7 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar) static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) { struct cfg80211_chan_def *chandef = NULL; - struct ieee80211_channel *channel = chandef-chan; + struct ieee80211_channel *channel; struct wmi_vdev_start_request_arg arg = {}; int ret = 0; There is a similar change integrated recently, https://github.com/kvalo/ath/commit/19be9e9a7ac7e6050eab426283d2a87593cf6e82 . Vasanth -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ath10k: Add QCA99X0 to supported device list
Add vendor/device id of QCA99X0 V2.0 to pci id table and QCA99X0_HW_2_0_CHIP_ID_REV to ath10k_pci_supp_chips[] for QCA99X0 to get detected by the driver. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 5778e52..cc0e897 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -64,6 +64,7 @@ MODULE_PARM_DESC(reset_mode, 0: auto, 1: warm only (default: 0)); static const struct pci_device_id ath10k_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ { PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */ + { PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */ {0} }; @@ -78,6 +79,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_0_CHIP_ID_REV }, { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_1_CHIP_ID_REV }, { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV }, + { QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV }, }; static void ath10k_pci_buffer_cleanup(struct ath10k *ar); -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2] ath10k: Delay device access after cold reset
It is observed that during cold reset pcie access right after a write operation to SOC_GLOBAL_RESET_ADDRESS causes Data Bus Error and system hard lockup. The reason for bus error is that pcie needs some time to get back to stable state for any transaction during cold reset. Add delay of 20 msecs after write of SOC_GLOBAL_RESET_ADDRESS to fix this issue. This patch is tested on QCA988X. This is also tested on QCA99X0 which is WIP. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- V2: - Include tested hw in commit log. drivers/net/wireless/ath/ath10k/pci.c | 20 +++- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 1b4634a..130746b 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2761,7 +2761,6 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) static int ath10k_pci_cold_reset(struct ath10k *ar) { - int i; u32 val; ath10k_dbg(ar, ATH10K_DBG_BOOT, boot cold reset\n); @@ -2777,23 +2776,18 @@ static int ath10k_pci_cold_reset(struct ath10k *ar) val |= 1; ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val); - for (i = 0; i ATH_PCI_RESET_WAIT_MAX; i++) { - if (ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) - RTC_STATE_COLD_RESET_MASK) - break; - msleep(1); - } + /* After writing into SOC_GLOBAL_RESET to put device into +* reset and pulling out of reset pcie may not be stable +* for any immediate pcie register access and cause bus error, +* add delay before any pcie access request to fix this issue. +*/ + msleep(20); /* Pull Target, including PCIe, out of RESET. */ val = ~1; ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val); - for (i = 0; i ATH_PCI_RESET_WAIT_MAX; i++) { - if (!(ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) - RTC_STATE_COLD_RESET_MASK)) - break; - msleep(1); - } + msleep(20); ath10k_dbg(ar, ATH10K_DBG_BOOT, boot cold reset complete\n); -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ath10k: Fix target to cpu address conversion logic
'commit 418ca5992e2f (ath10k: Make target cpu address to CE address conversion chip specific)' mask 0x7fff is added by mistake instead of 0x7ff. Fix this regression. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 130746b..a69bfa4 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -765,7 +765,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) case ATH10K_HW_QCA6174: val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS) - 0x7fff) 21; + 0x7ff) 21; break; case ATH10K_HW_QCA99X0: val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ath10k: Delay device access after cold reset
It is observed that during cold reset pcie access right after a write operation to SOC_GLOBAL_RESET_ADDRESS causes Data Bus Error and system hard lockup. The reason for bus error is that pcie needs some time to get back to stable state for any transaction during cold reset. Add delay of 20 msecs after write of SOC_GLOBAL_RESET_ADDRESS to fix this issue. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/pci.c | 20 +++- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 1b4634a..130746b 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2761,7 +2761,6 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) static int ath10k_pci_cold_reset(struct ath10k *ar) { - int i; u32 val; ath10k_dbg(ar, ATH10K_DBG_BOOT, boot cold reset\n); @@ -2777,23 +2776,18 @@ static int ath10k_pci_cold_reset(struct ath10k *ar) val |= 1; ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val); - for (i = 0; i ATH_PCI_RESET_WAIT_MAX; i++) { - if (ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) - RTC_STATE_COLD_RESET_MASK) - break; - msleep(1); - } + /* After writing into SOC_GLOBAL_RESET to put device into +* reset and pulling out of reset pcie may not be stable +* for any immediate pcie register access and cause bus error, +* add delay before any pcie access request to fix this issue. +*/ + msleep(20); /* Pull Target, including PCIe, out of RESET. */ val = ~1; ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val); - for (i = 0; i ATH_PCI_RESET_WAIT_MAX; i++) { - if (!(ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) - RTC_STATE_COLD_RESET_MASK)) - break; - msleep(1); - } + msleep(20); ath10k_dbg(ar, ATH10K_DBG_BOOT, boot cold reset complete\n); -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V2 09/10] ath10k: Add support for code swap
On Monday 29 June 2015 04:51 PM, Kalle Valo wrote: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com writes: Code swap is a mechanism to use host memory to store some fw binary code segment. Ath10k host driver allocates and loads the code swap binary into the host memory and configures the target with the host allocated memory information at the address taken from code swap binary. This patch adds code swap support for firmware binary. Code swap binary for firmware bin is available in ATH10K_FW_IE_FW_CODE_SWAP_IMAGE. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com [...] +static struct ath10k_swap_code_seg_info * +ath10k_swap_code_seg_alloc(struct ath10k *ar, size_t swap_bin_len) +{ + struct ath10k_swap_code_seg_info *seg_info; + void *virt_addr; + dma_addr_t paddr; + + swap_bin_len = roundup(swap_bin_len, 2); + if (swap_bin_len ATH10K_SWAP_CODE_SEG_BIN_LEN_MAX) { + ath10k_err(ar, refusing code swap bin because it is too big %zd %d\n, + swap_bin_len, ATH10K_SWAP_CODE_SEG_BIN_LEN_MAX); kbuild found a bug here, I fixed it with the patch below. Please review: --- a/drivers/net/wireless/ath/ath10k/swap.c +++ b/drivers/net/wireless/ath/ath10k/swap.c @@ -106,7 +106,7 @@ ath10k_swap_code_seg_alloc(struct ath10k *ar, size_t swap_bin_len) swap_bin_len = roundup(swap_bin_len, 2); if (swap_bin_len ATH10K_SWAP_CODE_SEG_BIN_LEN_MAX) { - ath10k_err(ar, refusing code swap bin because it is too big %zd %d\n, + ath10k_err(ar, refusing code swap bin because it is too big %zu %d\n, swap_bin_len, ATH10K_SWAP_CODE_SEG_BIN_LEN_MAX); return NULL; } Looks good. Thanks. Vasanth -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 01/10] ath10k: Add a table to store hw specific values
This is to prepare ath10k to support newer chip set. Values like CE_COUNT, MSI_ASSIGN_CE_MAX and RTC_STATE_V_ON can be different for different chips. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/core.c | 2 ++ drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/hw.c | 14 ++ drivers/net/wireless/ath/ath10k/hw.h | 18 +++--- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index f5db432..b17541b 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1514,9 +1514,11 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, switch (hw_rev) { case ATH10K_HW_QCA988X: ar-regs = qca988x_regs; + ar-hw_values = qca988x_values; break; case ATH10K_HW_QCA6174: ar-regs = qca6174_regs; + ar-hw_values = qca6174_values; break; default: ath10k_err(ar, unsupported core hardware revision %d\n, diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index e9f9304..993cd36 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -560,6 +560,7 @@ struct ath10k { struct completion target_suspend; const struct ath10k_hw_regs *regs; + const struct ath10k_hw_values *hw_values; struct ath10k_bmi bmi; struct ath10k_wmi wmi; struct ath10k_htc htc; diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 5997f00..48bcd2c 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -58,6 +58,20 @@ const struct ath10k_hw_regs qca6174_regs = { .scratch_3_address = 0x0028, }; +const struct ath10k_hw_values qca988x_values = { + .rtc_state_val_on = 3, + .ce_count = 8, + .msi_assign_ce_max = 7, + .num_target_ce_config_wlan = 7, +}; + +const struct ath10k_hw_values qca6174_values = { + .rtc_state_val_on = 3, + .ce_count = 8, + .msi_assign_ce_max = 7, + .num_target_ce_config_wlan = 7, +}; + void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) { diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 85cca29..b218388 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -169,6 +169,16 @@ struct ath10k_hw_regs { extern const struct ath10k_hw_regs qca988x_regs; extern const struct ath10k_hw_regs qca6174_regs; +struct ath10k_hw_values { + u32 rtc_state_val_on; + u8 ce_count; + u8 msi_assign_ce_max; + u8 num_target_ce_config_wlan; +}; + +extern const struct ath10k_hw_values qca988x_values; +extern const struct ath10k_hw_values qca6174_values; + void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev); @@ -310,8 +320,10 @@ enum ath10k_hw_rate_cck { #define TARGET_TLV_NUM_MSDU_DESC (1024 + 32) #define TARGET_TLV_NUM_WOW_PATTERNS22 +#define NUM_TARGET_CE_CONFIG_WLAN ar-hw_values-num_target_ce_config_wlan + /* Number of Copy Engines supported */ -#define CE_COUNT 8 +#define CE_COUNT ar-hw_values-ce_count /* * Total number of PCIe MSI interrupts requested for all interrupt sources. @@ -335,10 +347,10 @@ enum ath10k_hw_rate_cck { /* MSIs for Copy Engines */ #define MSI_ASSIGN_CE_INITIAL 1 -#define MSI_ASSIGN_CE_MAX 7 +#define MSI_ASSIGN_CE_MAX ar-hw_values-msi_assign_ce_max /* as of IP3.7.1 */ -#define RTC_STATE_V_ON 3 +#define RTC_STATE_V_ON ar-hw_values-rtc_state_val_on #define RTC_STATE_COLD_RESET_MASK ar-regs-rtc_state_cold_reset_mask #define RTC_STATE_V_LSB0 -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 02/10] ath10k: Add new reg_address/mask to hw register table
Add more register address and mask which can be different for newer chip to hw_reg table. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/ce.h | 6 -- drivers/net/wireless/ath/ath10k/hw.c | 22 ++ drivers/net/wireless/ath/ath10k/hw.h | 17 - 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 0eddb20..93939de 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -423,8 +423,10 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) (nentries_mask)) -#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 -#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0xff00 +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \ + ar-regs-ce_wrap_intr_sum_host_msi_lsb +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK \ + ar-regs-ce_wrap_intr_sum_host_msi_mask #define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(x) \ (((x) CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) \ CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 48bcd2c..cb09867 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -34,8 +34,15 @@ const struct ath10k_hw_regs qca988x_regs = { .ce7_base_address = 0x00059000, .soc_reset_control_si0_rst_mask = 0x0001, .soc_reset_control_ce_rst_mask = 0x0004, - .soc_chip_id_address= 0x00ec, - .scratch_3_address = 0x0030, + .soc_chip_id_address= 0x00ec, + .scratch_3_address = 0x0030, + .fw_indicator_address = 0x9030, + .pcie_local_base_address= 0x0008, + .ce_wrap_intr_sum_host_msi_lsb = 0x0008, + .ce_wrap_intr_sum_host_msi_mask = 0xff00, + .pcie_intr_fw_mask = 0x0400, + .pcie_intr_ce_mask_all = 0x0007f800, + .pcie_intr_clr_address = 0x0014, }; const struct ath10k_hw_regs qca6174_regs = { @@ -54,8 +61,15 @@ const struct ath10k_hw_regs qca6174_regs = { .ce7_base_address = 0x00036000, .soc_reset_control_si0_rst_mask = 0x, .soc_reset_control_ce_rst_mask = 0x0001, - .soc_chip_id_address= 0x000f0, - .scratch_3_address = 0x0028, + .soc_chip_id_address= 0x00f0, + .scratch_3_address = 0x0028, + .fw_indicator_address = 0x9028, + .pcie_local_base_address= 0x0008, + .ce_wrap_intr_sum_host_msi_lsb = 0x0008, + .ce_wrap_intr_sum_host_msi_mask = 0xff00, + .pcie_intr_fw_mask = 0x0400, + .pcie_intr_ce_mask_all = 0x0007f800, + .pcie_intr_clr_address = 0x0014, }; const struct ath10k_hw_values qca988x_values = { diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index b218388..5d04317 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -164,6 +164,13 @@ struct ath10k_hw_regs { u32 soc_reset_control_ce_rst_mask; u32 soc_chip_id_address; u32 scratch_3_address; + u32 fw_indicator_address; + u32 pcie_local_base_address; + u32 ce_wrap_intr_sum_host_msi_lsb; + u32 ce_wrap_intr_sum_host_msi_mask; + u32 pcie_intr_fw_mask; + u32 pcie_intr_ce_mask_all; + u32 pcie_intr_clr_address; }; extern const struct ath10k_hw_regs qca988x_regs; @@ -386,7 +393,7 @@ enum ath10k_hw_rate_cck { #define CE7_BASE_ADDRESS ar-regs-ce7_base_address #define DBI_BASE_ADDRESS 0x0006 #define WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x0006c000 -#define PCIE_LOCAL_BASE_ADDRESS0x0008 +#define PCIE_LOCAL_BASE_ADDRESS ar-regs-pcie_local_base_address #define SOC_RESET_CONTROL_ADDRESS 0x #define SOC_RESET_CONTROL_OFFSET 0x @@ -460,7 +467,7 @@ enum ath10k_hw_rate_cck { #define CORE_CTRL_ADDRESS 0x #define PCIE_INTR_ENABLE_ADDRESS 0x0008 #define PCIE_INTR_CAUSE_ADDRESS0x000c -#define PCIE_INTR_CLR_ADDRESS 0x0014 +#define PCIE_INTR_CLR_ADDRESS ar-regs-pcie_intr_clr_address #define SCRATCH_3_ADDRESS ar-regs
[PATCH V2 06/10] ath10k: Add chip reset sequence for QCA99X0
QCA99X0 supports only cold reset. Also, made ath10k_pci_irq_msi_fw_mask() and ath10k_pci_irq_msi_fw_unmask() non-99X0 specific till we get proper register configuration to mask/unmask irq/MSI. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/pci.c | 81 ++- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index df7d74e..1b4634a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -82,7 +82,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { static void ath10k_pci_buffer_cleanup(struct ath10k *ar); static int ath10k_pci_cold_reset(struct ath10k *ar); -static int ath10k_pci_warm_reset(struct ath10k *ar); +static int ath10k_pci_safe_chip_reset(struct ath10k *ar); static int ath10k_pci_wait_for_target_init(struct ath10k *ar); static int ath10k_pci_init_irq(struct ath10k *ar); static int ath10k_pci_deinit_irq(struct ath10k *ar); @@ -91,6 +91,7 @@ static void ath10k_pci_free_irq(struct ath10k *ar); static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, struct ath10k_ce_pipe *rx_pipe, struct bmi_xfer *xfer); +static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar); static const struct ce_attr host_ce_config_wlan[] = { /* CE0: host-target HTC control and raw streams */ @@ -1427,20 +1428,42 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) { u32 val; - val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); - val = ~CORE_CTRL_PCIE_REG_31_MASK; - - ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); + switch (ar-hw_rev) { + case ATH10K_HW_QCA988X: + case ATH10K_HW_QCA6174: + val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS); + val = ~CORE_CTRL_PCIE_REG_31_MASK; + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS, val); + break; + case ATH10K_HW_QCA99X0: + /* TODO: Find appropriate register configuration for QCA99X0 +* to mask irq/MSI. +*/ +break; + } } static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) { u32 val; - val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); - val |= CORE_CTRL_PCIE_REG_31_MASK; - - ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); + switch (ar-hw_rev) { + case ATH10K_HW_QCA988X: + case ATH10K_HW_QCA6174: + val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS); + val |= CORE_CTRL_PCIE_REG_31_MASK; + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS, val); + break; + case ATH10K_HW_QCA99X0: + /* TODO: Find appropriate register configuration for QCA99X0 +* to unmask irq/MSI. +*/ + break; + } } static void ath10k_pci_irq_disable(struct ath10k *ar) @@ -1602,7 +1625,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) * masked. To prevent the device from asserting the interrupt reset it * before proceeding with cleanup. */ - ath10k_pci_warm_reset(ar); + ath10k_pci_safe_chip_reset(ar); ath10k_pci_irq_disable(ar); ath10k_pci_irq_sync(ar); @@ -2114,6 +2137,18 @@ static int ath10k_pci_warm_reset(struct ath10k *ar) return 0; } +static int ath10k_pci_safe_chip_reset(struct ath10k *ar) +{ + if (QCA_REV_988X(ar) || QCA_REV_6174(ar)) { + return ath10k_pci_warm_reset(ar); + } else if (QCA_REV_99X0(ar)) { + ath10k_pci_irq_disable(ar); + return ath10k_pci_qca99x0_chip_reset(ar); + } else { + return -ENOTSUPP; + } +} + static int ath10k_pci_qca988x_chip_reset(struct ath10k *ar) { int i, ret; @@ -2220,12 +2255,38 @@ static int ath10k_pci_qca6174_chip_reset(struct ath10k *ar) return 0; } +static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar) +{ + int ret; + + ath10k_dbg(ar, ATH10K_DBG_BOOT, boot qca99x0 chip reset\n); + + ret = ath10k_pci_cold_reset(ar); + if (ret) { + ath10k_warn(ar, failed to cold reset: %d\n, ret); + return ret; + } + + ret = ath10k_pci_wait_for_target_init(ar); + if (ret) { + ath10k_warn(ar, failed to wait for target after cold reset: %d\n, + ret); + return ret
Re: [PATCH 00/10] Add QCA99X0 support
On Thu, Jun 18, 2015 at 09:20:51AM +0300, Kalle Valo wrote: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com writes: This patch set adds changes for QCA99X0 chip in pci probe, Copy Engine init and firmware downloads. Since it is still work in progress the support for this chip is not yet advertised in pci device table. Vasanthakumar Thiagarajan (10): ath10k: Add a table to store hw specific values ath10k: Add new reg_address/mask to hw register table ath10k: Add hw register/values for QCA99X0 chip ath10k: Copy Engine related changes for QCA99X0 ath10k: Make target cpu address to CE address conversion chip specific ath10k: Add chip reset sequence for QCA99X0 ath10k: Extend CE src desc flags for interrupt indication ath10k: Fix BMI communication timeout for QCA99X0 ath10k: Add support for code swap ath10k: Add BMI param value to execute otp to hw_param These patches don't apply and don't have proper sha1 ids. Please rebase. And remember always to use ath.git master branch as the baseline, don't apply any custom patches because that will break 3-way merge. Applying: ath10k: Add a table to store hw specific values Applying: ath10k: Add new reg_address/mask to hw register table Applying: ath10k: Add hw register/values for QCA99X0 chip fatal: sha1 information is lacking or useless (drivers/net/wireless/ath/ath10k/core.c). Repository lacks necessary blobs to fall back on 3-way merge. Cannot fall back to three-way merge. Patch failed at 0003 ath10k: Add hw register/values for QCA99X0 chip Sorry about this. Im sending the rebased patches on top of ath.git master tot Vasanth -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 05/10] ath10k: Make target cpu address to CE address conversion chip specific
Make the helper converting target virtual address space to CE address space a target type specific to support QCA99X0. Also make this as function instead of macro. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/pci.c | 25 ++--- drivers/net/wireless/ath/ath10k/pci.h | 12 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index c2aecfe..df7d74e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -755,6 +755,26 @@ static void ath10k_pci_rx_replenish_retry(unsigned long ptr) ath10k_pci_rx_post(ar); } +static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) +{ + u32 val = 0; + + switch (ar-hw_rev) { + case ATH10K_HW_QCA988X: + case ATH10K_HW_QCA6174: + val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS) + 0x7fff) 21; + break; + case ATH10K_HW_QCA99X0: + val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); + break; + } + + val |= 0x10 | (addr 0xf); + return val; +} + /* * Diagnostic read/write access is provided for startup/config/debug usage. * Caller must guarantee proper alignment, when applicable, and single user @@ -817,8 +837,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, * convert it from Target CPU virtual address space * to CE address space */ - address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci-mem, -address); + address = ath10k_pci_targ_cpu_to_ce_addr(ar, address); ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0, 0); @@ -976,7 +995,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, * to *CE address space */ - address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci-mem, address); + address = ath10k_pci_targ_cpu_to_ce_addr(ar, address); remaining_bytes = orig_nbytes; ce_data = ce_data_base; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index eea0a01..8d364fb 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -237,18 +237,6 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) #define CDC_WAR_MAGIC_STR 0xceef #define CDC_WAR_DATA_CE 4 -/* - * TODO: Should be a function call specific to each Target-type. - * This convoluted macro converts from Target CPU Virtual Address Space to CE - * Address Space. As part of this process, we conservatively fetch the current - * PCIE_BAR. MOST of the time, this should match the upper bits of PCI space - * for this device; but that's not guaranteed. - */ -#define TARG_CPU_SPACE_TO_CE_SPACE(ar, pci_addr, addr) \ - (((ath10k_pci_read32(ar, (SOC_CORE_BASE_ADDRESS | \ - CORE_CTRL_ADDRESS)) 0x7ff) 21) | \ -0x10 | ((addr) 0xf)) - /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */ #define DIAG_ACCESS_CE_TIMEOUT_MS 10 -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 03/10] ath10k: Add hw register/values for QCA99X0 chip
This is to prepare the driver for QCA99X0 chip support. This commit adds hw_params, hw register table and hw_values table for QCA99X0 chip. Please note this is only a partial patch adding support for QCA99X0, so the device id is not yet added to pci device table. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/core.c | 18 drivers/net/wireless/ath/ath10k/hw.c| 44 + drivers/net/wireless/ath/ath10k/hw.h| 18 drivers/net/wireless/ath/ath10k/pci.c | 5 drivers/net/wireless/ath/ath10k/targaddrs.h | 3 ++ 5 files changed, 88 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b17541b..f239e96 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -101,6 +101,20 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, }, + { + .id = QCA99X0_HW_2_0_DEV_VERSION, + .name = qca99x0 hw2.0, + .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .fw = { + .dir = QCA99X0_HW_2_0_FW_DIR, + .fw = QCA99X0_HW_2_0_FW_FILE, + .otp = QCA99X0_HW_2_0_OTP_FILE, + .board = QCA99X0_HW_2_0_BOARD_DATA_FILE, + .board_size = QCA99X0_BOARD_DATA_SZ, + .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, + }, + }, }; static const char *const ath10k_core_fw_feature_str[] = { @@ -1520,6 +1534,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar-regs = qca6174_regs; ar-hw_values = qca6174_values; break; + case ATH10K_HW_QCA99X0: + ar-regs = qca99x0_regs; + ar-hw_values = qca99x0_values; + break; default: ath10k_err(ar, unsupported core hardware revision %d\n, hw_rev); diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index cb09867..e5fe33d9 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -72,6 +72,43 @@ const struct ath10k_hw_regs qca6174_regs = { .pcie_intr_clr_address = 0x0014, }; +const struct ath10k_hw_regs qca99x0_regs = { + .rtc_state_cold_reset_mask = 0x0400, + .rtc_soc_base_address = 0x0008, + .rtc_wmac_base_address = 0x, + .soc_core_base_address = 0x00082000, + .ce_wrapper_base_address= 0x0004d000, + .ce0_base_address = 0x0004a000, + .ce1_base_address = 0x0004a400, + .ce2_base_address = 0x0004a800, + .ce3_base_address = 0x0004ac00, + .ce4_base_address = 0x0004b000, + .ce5_base_address = 0x0004b400, + .ce6_base_address = 0x0004b800, + .ce7_base_address = 0x0004bc00, + /* Note: qca99x0 supports upto 12 Copy Engines. Other than address of +* CE0 and CE1 no other copy engine is directly referred in the code. +* It is not really neccessary to assign address for newly supported +* CEs in this address table. +* Copy Engine Address +* CE8 0x0004c000 +* CE9 0x0004c400 +* CE100x0004c800 +* CE110x0004cc00 +*/ + .soc_reset_control_si0_rst_mask = 0x0001, + .soc_reset_control_ce_rst_mask = 0x0100, + .soc_chip_id_address= 0x00ec, + .scratch_3_address = 0x00040050, + .fw_indicator_address = 0x00040050, + .pcie_local_base_address= 0x, + .ce_wrap_intr_sum_host_msi_lsb = 0x000c, + .ce_wrap_intr_sum_host_msi_mask = 0x00fff000, + .pcie_intr_fw_mask = 0x0010, + .pcie_intr_ce_mask_all = 0x000fff00, + .pcie_intr_clr_address = 0x0010, +}; + const struct ath10k_hw_values qca988x_values = { .rtc_state_val_on = 3, .ce_count = 8, @@ -86,6 +123,13 @@ const struct ath10k_hw_values qca6174_values = { .num_target_ce_config_wlan = 7, }; +const struct ath10k_hw_values qca99x0_values = { + .rtc_state_val_on
[PATCH V2 04/10] ath10k: Copy Engine related changes for QCA99X0
QCA99X0 supports upto 12 Copy engines. Host and target CE configuration table is updated to support new copy engine pipes. This also fixes the assumption of diagnostic CE by making CE_7 as the one instead of CE_COUNT - 1. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/ce.h | 2 +- drivers/net/wireless/ath/ath10k/hw.h | 3 ++ drivers/net/wireless/ath/ath10k/pci.c | 69 ++- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 93939de..bb4b8f3 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -21,7 +21,7 @@ #include hif.h /* Maximum number of Copy Engine's supported */ -#define CE_COUNT_MAX 8 +#define CE_COUNT_MAX 12 #define CE_HTT_H2T_MSG_SRC_NENTRIES 4096 /* Descriptor rings must be aligned to this boundary */ diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 76caeab..5819659 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -343,6 +343,9 @@ enum ath10k_hw_rate_cck { #define TARGET_TLV_NUM_MSDU_DESC (1024 + 32) #define TARGET_TLV_NUM_WOW_PATTERNS22 +/* Diagnostic Window */ +#define CE_DIAG_PIPE 7 + #define NUM_TARGET_CE_CONFIG_WLAN ar-hw_values-num_target_ce_config_wlan /* Number of Copy Engines supported */ diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 0007e70..c2aecfe 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -156,6 +156,38 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_sz_max = DIAG_TRANSFER_LIMIT, .dest_nentries = 2, }, + + /* CE8: target-host pktlog */ + { + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 2048, + .dest_nentries = 128, + }, + + /* CE9 target autonomous qcache memcpy */ + { + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 0, + .dest_nentries = 0, + }, + + /* CE10: target autonomous hif memcpy */ + { + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 0, + .dest_nentries = 0, + }, + + /* CE11: target autonomous hif memcpy */ + { + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 0, + .dest_nentries = 0, + }, }; /* Target firmware's Copy Engine configuration. */ @@ -233,6 +265,38 @@ static const struct ce_pipe_config target_ce_config_wlan[] = { }, /* CE7 used only by Host */ + { + .pipenum = __cpu_to_le32(7), + .pipedir = __cpu_to_le32(PIPEDIR_INOUT), + .nentries = __cpu_to_le32(0), + .nbytes_max = __cpu_to_le32(0), + .flags = __cpu_to_le32(0), + .reserved = __cpu_to_le32(0), + }, + + /* CE8 target-host packtlog */ + { + .pipenum = __cpu_to_le32(8), + .pipedir = __cpu_to_le32(PIPEDIR_IN), + .nentries = __cpu_to_le32(64), + .nbytes_max = __cpu_to_le32(2048), + .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR), + .reserved = __cpu_to_le32(0), + }, + + /* CE9 target autonomous qcache memcpy */ + { + .pipenum = __cpu_to_le32(9), + .pipedir = __cpu_to_le32(PIPEDIR_INOUT), + .nentries = __cpu_to_le32(32), + .nbytes_max = __cpu_to_le32(2048), + .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR), + .reserved = __cpu_to_le32(0), + }, + + /* It not necessary to send target wlan configuration for CE10 CE11 +* as these CEs are not actively used in target. +*/ }; /* @@ -1771,7 +1835,8 @@ static int ath10k_pci_init_config(struct ath10k *ar) ret = ath10k_pci_diag_write_mem(ar, pipe_cfg_targ_addr, target_ce_config_wlan, - sizeof(target_ce_config_wlan)); + sizeof(struct ce_pipe_config) * + NUM_TARGET_CE_CONFIG_WLAN); if (ret != 0) { ath10k_err(ar, Failed to write pipe cfg: %d\n, ret); @@ -1885,7 +1950,7 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar) } /* Last CE is Diagnostic Window */ - if (i == CE_COUNT - 1) { + if (i == CE_DIAG_PIPE) { ar_pci-ce_diag = pipe-ce_hdl; continue
[PATCH V2 07/10] ath10k: Extend CE src desc flags for interrupt indication
QCA99X0 uses two new copy engine src desc flags for interrupt indication. Bit_2 is to mark if host interrupt is disabled after processing the current desc and bit_3 is to mark if target interrupt is diabled after the processing of current descriptor. CE_DESC_FLAGS_META_DATA_MASK and CE_DESC_FLAGS_META_DATA_LSB are based on the target type. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/ce.c | 1 + drivers/net/wireless/ath/ath10k/ce.h | 9 +++-- drivers/net/wireless/ath/ath10k/hw.c | 6 ++ drivers/net/wireless/ath/ath10k/hw.h | 2 ++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index e508c65..cf28fbe 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -452,6 +452,7 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, { struct ath10k_ce_ring *dest_ring = ce_state-dest_ring; unsigned int nentries_mask = dest_ring-nentries_mask; + struct ath10k *ar = ce_state-ar; unsigned int sw_index = dest_ring-sw_index; struct ce_desc *base = dest_ring-base_addr_owner_space; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index bb4b8f3..5c903e15 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -38,8 +38,13 @@ struct ath10k_ce_pipe; #define CE_DESC_FLAGS_GATHER (1 0) #define CE_DESC_FLAGS_BYTE_SWAP (1 1) -#define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC -#define CE_DESC_FLAGS_META_DATA_LSB 2 + +/* Following desc flags are used in QCA99X0 */ +#define CE_DESC_FLAGS_HOST_INT_DIS (1 2) +#define CE_DESC_FLAGS_TGT_INT_DIS (1 3) + +#define CE_DESC_FLAGS_META_DATA_MASK ar-hw_values-ce_desc_meta_data_mask +#define CE_DESC_FLAGS_META_DATA_LSB ar-hw_values-ce_desc_meta_data_lsb struct ce_desc { __le32 addr; diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index e5fe33d9..1414e1f 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -114,6 +114,8 @@ const struct ath10k_hw_values qca988x_values = { .ce_count = 8, .msi_assign_ce_max = 7, .num_target_ce_config_wlan = 7, + .ce_desc_meta_data_mask = 0xFFFC, + .ce_desc_meta_data_lsb = 2, }; const struct ath10k_hw_values qca6174_values = { @@ -121,6 +123,8 @@ const struct ath10k_hw_values qca6174_values = { .ce_count = 8, .msi_assign_ce_max = 7, .num_target_ce_config_wlan = 7, + .ce_desc_meta_data_mask = 0xFFFC, + .ce_desc_meta_data_lsb = 2, }; const struct ath10k_hw_values qca99x0_values = { @@ -128,6 +132,8 @@ const struct ath10k_hw_values qca99x0_values = { .ce_count = 12, .msi_assign_ce_max = 12, .num_target_ce_config_wlan = 10, + .ce_desc_meta_data_mask = 0xFFF0, + .ce_desc_meta_data_lsb = 4, }; void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 5819659..35cd8ca 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -195,6 +195,8 @@ struct ath10k_hw_values { u8 ce_count; u8 msi_assign_ce_max; u8 num_target_ce_config_wlan; + u16 ce_desc_meta_data_mask; + u8 ce_desc_meta_data_lsb; }; extern const struct ath10k_hw_values qca988x_values; -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 09/10] ath10k: Add support for code swap
Code swap is a mechanism to use host memory to store some fw binary code segment. Ath10k host driver allocates and loads the code swap binary into the host memory and configures the target with the host allocated memory information at the address taken from code swap binary. This patch adds code swap support for firmware binary. Code swap binary for firmware bin is available in ATH10K_FW_IE_FW_CODE_SWAP_IMAGE. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/Makefile | 3 +- drivers/net/wireless/ath/ath10k/core.c | 24 drivers/net/wireless/ath/ath10k/core.h | 7 ++ drivers/net/wireless/ath/ath10k/hw.h | 3 + drivers/net/wireless/ath/ath10k/swap.c | 208 +++ drivers/net/wireless/ath/ath10k/swap.h | 72 +++ 6 files changed, 316 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/ath/ath10k/swap.c create mode 100644 drivers/net/wireless/ath/ath10k/swap.h diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index 9729e69..c04fb00 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -11,7 +11,8 @@ ath10k_core-y += mac.o \ wmi-tlv.o \ bmi.o \ hw.o \ -p2p.o +p2p.o \ +swap.o ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index f239e96..c5f5d16 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -470,6 +470,13 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) data = ar-firmware_data; data_len = ar-firmware_len; mode_name = normal; + ret = ath10k_swap_code_seg_configure(ar, + ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); + if (ret) { + ath10k_err(ar, failed to configure fw code swap: %d\n, + ret); + return ret; + } break; case ATH10K_FIRMWARE_MODE_UTF: data = ar-testmode.utf-data; @@ -509,6 +516,8 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) if (!IS_ERR(ar-cal_file)) release_firmware(ar-cal_file); + ath10k_swap_code_seg_release(ar); + ar-board = NULL; ar-board_data = NULL; ar-board_len = 0; @@ -522,6 +531,7 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ar-firmware_len = 0; ar-cal_file = NULL; + } static int ath10k_fetch_cal_file(struct ath10k *ar) @@ -795,6 +805,13 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) ath10k_dbg(ar, ATH10K_DBG_BOOT, found fw ie htt op version %d\n, ar-htt.op_version); break; + case ATH10K_FW_IE_FW_CODE_SWAP_IMAGE: + ath10k_dbg(ar, ATH10K_DBG_BOOT, + found fw code swap image ie (%zd B)\n, + ie_len); + ar-swap.firmware_codeswap_data = data; + ar-swap.firmware_codeswap_len = ie_len; + break; default: ath10k_warn(ar, Unknown FW IE: %u\n, le32_to_cpu(hdr-id)); @@ -1388,6 +1405,13 @@ static int ath10k_core_probe_fw(struct ath10k *ar) goto err_free_firmware_files; } + ret = ath10k_swap_code_seg_init(ar); + if (ret) { + ath10k_err(ar, failed to initialize code swap segment: %d\n, + ret); + goto err_free_firmware_files; + } + mutex_lock(ar-conf_mutex); ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 993cd36..b9145f5 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -36,6 +36,7 @@ #include spectral.h #include thermal.h #include wow.h +#include swap.h #define MS(_v, _f) (((_v) _f##_MASK) _f##_LSB) #define SM(_v, _f) (((_v) _f##_LSB) _f##_MASK) @@ -603,6 +604,12 @@ struct ath10k { const struct firmware *cal_file; + struct { + const void *firmware_codeswap_data; + size_t firmware_codeswap_len; + struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info; + } swap; + char spec_board_id[100]; bool spec_board_loaded; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net
[PATCH V2 08/10] ath10k: Fix BMI communication timeout for QCA99X0
There is more than 1 sec delay in getting response from target through BMI in QCA99X0. Increase the BMI communication timeout to 2*HZ to fix BMI failures. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/bmi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h index 31a9906..df7c761 100644 --- a/drivers/net/wireless/ath/ath10k/bmi.h +++ b/drivers/net/wireless/ath/ath10k/bmi.h @@ -178,7 +178,7 @@ struct bmi_target_info { }; /* in msec */ -#define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ) +#define BMI_COMMUNICATION_TIMEOUT_HZ (2 * HZ) #define BMI_CE_NUM_TO_TARG 0 #define BMI_CE_NUM_TO_HOST 1 -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 10/10] ath10k: Add BMI param value to execute otp to hw_param
BMI parameter value to execute downloaded otp binary is different for QCA99X0. Have a member in hw_params to hold hw specific BMI param. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/core.c | 8 +++- drivers/net/wireless/ath/ath10k/core.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index c5f5d16..80f38b5 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -49,6 +49,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, .has_shifted_cc_wraparound = true, + .otp_exe_param = 0, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, .fw = QCA988X_HW_2_0_FW_FILE, @@ -63,6 +64,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = qca6174 hw2.1, .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR, .uart_pin = 6, + .otp_exe_param = 0, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, .fw = QCA6174_HW_2_1_FW_FILE, @@ -77,6 +79,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = qca6174 hw3.0, .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, .uart_pin = 6, + .otp_exe_param = 0, .fw = { .dir = QCA6174_HW_3_0_FW_DIR, .fw = QCA6174_HW_3_0_FW_FILE, @@ -91,6 +94,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = qca6174 hw3.2, .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, .uart_pin = 6, + .otp_exe_param = 0, .fw = { /* uses same binaries as hw3.0 */ .dir = QCA6174_HW_3_0_FW_DIR, @@ -106,6 +110,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = qca99x0 hw2.0, .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, + .otp_exe_param = 0x0700, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, .fw = QCA99X0_HW_2_0_FW_FILE, @@ -413,6 +418,7 @@ out: static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar-hw_params.patch_load_addr; + u32 bmi_otp_exe_param = ar-hw_params.otp_exe_param; int ret; ret = ath10k_download_board_data(ar, ar-board_data, ar-board_len); @@ -438,7 +444,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) return ret; } - ret = ath10k_bmi_execute(ar, address, 0, result); + ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, result); if (ret) { ath10k_err(ar, could not execute otp (%d)\n, ret); return ret; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index b9145f5..afd21d5 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -572,6 +572,7 @@ struct ath10k { const char *name; u32 patch_load_addr; int uart_pin; + u32 otp_exe_param; /* This is true if given HW chip has a quirky Cycle Counter * wraparound which resets to 0x7fff instead of 0. All -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 07/10] ath10k: Extend CE src desc flags for interrupt indication
QCA99X0 uses two new copy engine src desc flags for interrupt indication. Bit_2 is to mark if host interrupt is disabled after processing the current desc and bit_3 is to mark if target interrupt is diabled after the processing of current descriptor. CE_DESC_FLAGS_META_DATA_MASK and CE_DESC_FLAGS_META_DATA_LSB are based on the target type. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/ce.c | 1 + drivers/net/wireless/ath/ath10k/ce.h | 9 +++-- drivers/net/wireless/ath/ath10k/hw.c | 6 ++ drivers/net/wireless/ath/ath10k/hw.h | 2 ++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index e508c65..cf28fbe 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -452,6 +452,7 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, { struct ath10k_ce_ring *dest_ring = ce_state-dest_ring; unsigned int nentries_mask = dest_ring-nentries_mask; + struct ath10k *ar = ce_state-ar; unsigned int sw_index = dest_ring-sw_index; struct ce_desc *base = dest_ring-base_addr_owner_space; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index bb4b8f3..5c903e15 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -38,8 +38,13 @@ struct ath10k_ce_pipe; #define CE_DESC_FLAGS_GATHER (1 0) #define CE_DESC_FLAGS_BYTE_SWAP (1 1) -#define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC -#define CE_DESC_FLAGS_META_DATA_LSB 2 + +/* Following desc flags are used in QCA99X0 */ +#define CE_DESC_FLAGS_HOST_INT_DIS (1 2) +#define CE_DESC_FLAGS_TGT_INT_DIS (1 3) + +#define CE_DESC_FLAGS_META_DATA_MASK ar-hw_values-ce_desc_meta_data_mask +#define CE_DESC_FLAGS_META_DATA_LSB ar-hw_values-ce_desc_meta_data_lsb struct ce_desc { __le32 addr; diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index e5fe33d9..1414e1f 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -114,6 +114,8 @@ const struct ath10k_hw_values qca988x_values = { .ce_count = 8, .msi_assign_ce_max = 7, .num_target_ce_config_wlan = 7, + .ce_desc_meta_data_mask = 0xFFFC, + .ce_desc_meta_data_lsb = 2, }; const struct ath10k_hw_values qca6174_values = { @@ -121,6 +123,8 @@ const struct ath10k_hw_values qca6174_values = { .ce_count = 8, .msi_assign_ce_max = 7, .num_target_ce_config_wlan = 7, + .ce_desc_meta_data_mask = 0xFFFC, + .ce_desc_meta_data_lsb = 2, }; const struct ath10k_hw_values qca99x0_values = { @@ -128,6 +132,8 @@ const struct ath10k_hw_values qca99x0_values = { .ce_count = 12, .msi_assign_ce_max = 12, .num_target_ce_config_wlan = 10, + .ce_desc_meta_data_mask = 0xFFF0, + .ce_desc_meta_data_lsb = 4, }; void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 5819659..35cd8ca 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -195,6 +195,8 @@ struct ath10k_hw_values { u8 ce_count; u8 msi_assign_ce_max; u8 num_target_ce_config_wlan; + u16 ce_desc_meta_data_mask; + u8 ce_desc_meta_data_lsb; }; extern const struct ath10k_hw_values qca988x_values; -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 08/10] ath10k: Fix BMI communication timeout for QCA99X0
There is more than 1 sec delay in getting response from target through BMI in QCA99X0. Increase the BMI communication timeout to 2*HZ to fix BMI failures. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/bmi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h index 31a9906..df7c761 100644 --- a/drivers/net/wireless/ath/ath10k/bmi.h +++ b/drivers/net/wireless/ath/ath10k/bmi.h @@ -178,7 +178,7 @@ struct bmi_target_info { }; /* in msec */ -#define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ) +#define BMI_COMMUNICATION_TIMEOUT_HZ (2 * HZ) #define BMI_CE_NUM_TO_TARG 0 #define BMI_CE_NUM_TO_HOST 1 -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/10] ath10k: Add support for code swap
Code swap is a mechanism to use host memory to store some fw binary code segment. Ath10k host driver allocates and loads the code swap binary into the host memory and configures the target with the host allocated memory information at the address taken from code swap binary. This patch adds code swap support for firmware binary. Code swap binary for firmware bin is available in ATH10K_FW_IE_FW_CODE_SWAP_IMAGE. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/Makefile | 3 +- drivers/net/wireless/ath/ath10k/core.c | 24 drivers/net/wireless/ath/ath10k/core.h | 7 ++ drivers/net/wireless/ath/ath10k/hw.h | 3 + drivers/net/wireless/ath/ath10k/swap.c | 208 +++ drivers/net/wireless/ath/ath10k/swap.h | 72 +++ 6 files changed, 316 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/ath/ath10k/swap.c create mode 100644 drivers/net/wireless/ath/ath10k/swap.h diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index 9729e69..c04fb00 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -11,7 +11,8 @@ ath10k_core-y += mac.o \ wmi-tlv.o \ bmi.o \ hw.o \ -p2p.o +p2p.o \ +swap.o ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index de85ec8..6346711 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -426,6 +426,13 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) data = ar-firmware_data; data_len = ar-firmware_len; mode_name = normal; + ret = ath10k_swap_code_seg_configure(ar, + ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); + if (ret) { + ath10k_err(ar, failed to configure fw code swap: %d\n, + ret); + return ret; + } break; case ATH10K_FIRMWARE_MODE_UTF: data = ar-testmode.utf-data; @@ -465,6 +472,8 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) if (!IS_ERR(ar-cal_file)) release_firmware(ar-cal_file); + ath10k_swap_code_seg_release(ar); + ar-board = NULL; ar-board_data = NULL; ar-board_len = 0; @@ -478,6 +487,7 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ar-firmware_len = 0; ar-cal_file = NULL; + } static int ath10k_fetch_cal_file(struct ath10k *ar) @@ -751,6 +761,13 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) ath10k_dbg(ar, ATH10K_DBG_BOOT, found fw ie htt op version %d\n, ar-htt.op_version); break; + case ATH10K_FW_IE_FW_CODE_SWAP_IMAGE: + ath10k_dbg(ar, ATH10K_DBG_BOOT, + found fw code swap image ie (%zd B)\n, + ie_len); + ar-swap.firmware_codeswap_data = data; + ar-swap.firmware_codeswap_len = ie_len; + break; default: ath10k_warn(ar, Unknown FW IE: %u\n, le32_to_cpu(hdr-id)); @@ -1344,6 +1361,13 @@ static int ath10k_core_probe_fw(struct ath10k *ar) goto err_free_firmware_files; } + ret = ath10k_swap_code_seg_init(ar); + if (ret) { + ath10k_err(ar, failed to initialize code swap segment: %d\n, + ret); + goto err_free_firmware_files; + } + mutex_lock(ar-conf_mutex); ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index ae92f64..335b2fc 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -36,6 +36,7 @@ #include spectral.h #include thermal.h #include wow.h +#include swap.h #define MS(_v, _f) (((_v) _f##_MASK) _f##_LSB) #define SM(_v, _f) (((_v) _f##_LSB) _f##_MASK) @@ -603,6 +604,12 @@ struct ath10k { const struct firmware *cal_file; + struct { + const void *firmware_codeswap_data; + size_t firmware_codeswap_len; + struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info; + } swap; + char spec_board_id[100]; bool spec_board_loaded; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net
[PATCH 03/10] ath10k: Add hw register/values for QCA99X0 chip
This is to prepare the driver for QCA99X0 chip support. This commit adds hw_params, hw register table and hw_values table for QCA99X0 chip. Please note this is only a partial patch adding support for QCA99X0, so the device id is not yet added to pci device table. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/core.c | 18 drivers/net/wireless/ath/ath10k/hw.c| 44 + drivers/net/wireless/ath/ath10k/hw.h| 18 drivers/net/wireless/ath/ath10k/pci.c | 5 drivers/net/wireless/ath/ath10k/targaddrs.h | 3 ++ 5 files changed, 88 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 2a17664..de85ec8 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -101,6 +101,20 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, }, + { + .id = QCA99X0_HW_2_0_DEV_VERSION, + .name = qca99x0 hw2.0, + .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .fw = { + .dir = QCA99X0_HW_2_0_FW_DIR, + .fw = QCA99X0_HW_2_0_FW_FILE, + .otp = QCA99X0_HW_2_0_OTP_FILE, + .board = QCA99X0_HW_2_0_BOARD_DATA_FILE, + .board_size = QCA99X0_BOARD_DATA_SZ, + .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, + }, + }, }; static void ath10k_send_suspend_complete(struct ath10k *ar) @@ -1476,6 +1490,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar-regs = qca6174_regs; ar-hw_values = qca6174_values; break; + case ATH10K_HW_QCA99X0: + ar-regs = qca99x0_regs; + ar-hw_values = qca99x0_values; + break; default: ath10k_err(ar, unsupported core hardware revision %d\n, hw_rev); diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index cb09867..e5fe33d9 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -72,6 +72,43 @@ const struct ath10k_hw_regs qca6174_regs = { .pcie_intr_clr_address = 0x0014, }; +const struct ath10k_hw_regs qca99x0_regs = { + .rtc_state_cold_reset_mask = 0x0400, + .rtc_soc_base_address = 0x0008, + .rtc_wmac_base_address = 0x, + .soc_core_base_address = 0x00082000, + .ce_wrapper_base_address= 0x0004d000, + .ce0_base_address = 0x0004a000, + .ce1_base_address = 0x0004a400, + .ce2_base_address = 0x0004a800, + .ce3_base_address = 0x0004ac00, + .ce4_base_address = 0x0004b000, + .ce5_base_address = 0x0004b400, + .ce6_base_address = 0x0004b800, + .ce7_base_address = 0x0004bc00, + /* Note: qca99x0 supports upto 12 Copy Engines. Other than address of +* CE0 and CE1 no other copy engine is directly referred in the code. +* It is not really neccessary to assign address for newly supported +* CEs in this address table. +* Copy Engine Address +* CE8 0x0004c000 +* CE9 0x0004c400 +* CE100x0004c800 +* CE110x0004cc00 +*/ + .soc_reset_control_si0_rst_mask = 0x0001, + .soc_reset_control_ce_rst_mask = 0x0100, + .soc_chip_id_address= 0x00ec, + .scratch_3_address = 0x00040050, + .fw_indicator_address = 0x00040050, + .pcie_local_base_address= 0x, + .ce_wrap_intr_sum_host_msi_lsb = 0x000c, + .ce_wrap_intr_sum_host_msi_mask = 0x00fff000, + .pcie_intr_fw_mask = 0x0010, + .pcie_intr_ce_mask_all = 0x000fff00, + .pcie_intr_clr_address = 0x0010, +}; + const struct ath10k_hw_values qca988x_values = { .rtc_state_val_on = 3, .ce_count = 8, @@ -86,6 +123,13 @@ const struct ath10k_hw_values qca6174_values = { .num_target_ce_config_wlan = 7, }; +const struct ath10k_hw_values qca99x0_values = { + .rtc_state_val_on
[PATCH 10/10] ath10k: Add BMI param value to execute otp to hw_param
BMI parameter value to execute downloaded otp binary is different for QCA99X0. Have a member in hw_params to hold hw specific BMI param. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/core.c | 8 +++- drivers/net/wireless/ath/ath10k/core.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 6346711..c6a39eeb 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -49,6 +49,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, .has_shifted_cc_wraparound = true, + .otp_exe_param = 0, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, .fw = QCA988X_HW_2_0_FW_FILE, @@ -63,6 +64,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = qca6174 hw2.1, .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR, .uart_pin = 6, + .otp_exe_param = 0, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, .fw = QCA6174_HW_2_1_FW_FILE, @@ -77,6 +79,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = qca6174 hw3.0, .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, .uart_pin = 6, + .otp_exe_param = 0, .fw = { .dir = QCA6174_HW_3_0_FW_DIR, .fw = QCA6174_HW_3_0_FW_FILE, @@ -91,6 +94,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = qca6174 hw3.2, .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, .uart_pin = 6, + .otp_exe_param = 0, .fw = { /* uses same binaries as hw3.0 */ .dir = QCA6174_HW_3_0_FW_DIR, @@ -106,6 +110,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .name = qca99x0 hw2.0, .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, + .otp_exe_param = 0x0700, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, .fw = QCA99X0_HW_2_0_FW_FILE, @@ -369,6 +374,7 @@ out: static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar-hw_params.patch_load_addr; + u32 bmi_otp_exe_param = ar-hw_params.otp_exe_param; int ret; ret = ath10k_download_board_data(ar, ar-board_data, ar-board_len); @@ -394,7 +400,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) return ret; } - ret = ath10k_bmi_execute(ar, address, 0, result); + ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, result); if (ret) { ath10k_err(ar, could not execute otp (%d)\n, ret); return ret; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 335b2fc..e9bf28e 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -572,6 +572,7 @@ struct ath10k { const char *name; u32 patch_load_addr; int uart_pin; + u32 otp_exe_param; /* This is true if given HW chip has a quirky Cycle Counter * wraparound which resets to 0x7fff instead of 0. All -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 06/10] ath10k: Add chip reset sequence for QCA99X0
QCA99X0 supports only cold reset. Also, made ath10k_pci_irq_msi_fw_mask() and ath10k_pci_irq_msi_fw_unmask() non-99X0 specific till we get proper register configuration to mask/unmask irq/MSI. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/pci.c | 81 ++- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 422232c..fe41b61 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -82,7 +82,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { static void ath10k_pci_buffer_cleanup(struct ath10k *ar); static int ath10k_pci_cold_reset(struct ath10k *ar); -static int ath10k_pci_warm_reset(struct ath10k *ar); +static int ath10k_pci_safe_chip_reset(struct ath10k *ar); static int ath10k_pci_wait_for_target_init(struct ath10k *ar); static int ath10k_pci_init_irq(struct ath10k *ar); static int ath10k_pci_deinit_irq(struct ath10k *ar); @@ -91,6 +91,7 @@ static void ath10k_pci_free_irq(struct ath10k *ar); static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, struct ath10k_ce_pipe *rx_pipe, struct bmi_xfer *xfer); +static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar); static const struct ce_attr host_ce_config_wlan[] = { /* CE0: host-target HTC control and raw streams */ @@ -1415,20 +1416,42 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) { u32 val; - val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); - val = ~CORE_CTRL_PCIE_REG_31_MASK; - - ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); + switch (ar-hw_rev) { + case ATH10K_HW_QCA988X: + case ATH10K_HW_QCA6174: + val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS); + val = ~CORE_CTRL_PCIE_REG_31_MASK; + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS, val); + break; + case ATH10K_HW_QCA99X0: + /* TODO: Find appropriate register configuration for QCA99X0 +* to mask irq/MSI. +*/ +break; + } } static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) { u32 val; - val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); - val |= CORE_CTRL_PCIE_REG_31_MASK; - - ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); + switch (ar-hw_rev) { + case ATH10K_HW_QCA988X: + case ATH10K_HW_QCA6174: + val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS); + val |= CORE_CTRL_PCIE_REG_31_MASK; + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS, val); + break; + case ATH10K_HW_QCA99X0: + /* TODO: Find appropriate register configuration for QCA99X0 +* to unmask irq/MSI. +*/ + break; + } } static void ath10k_pci_irq_disable(struct ath10k *ar) @@ -1590,7 +1613,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) * masked. To prevent the device from asserting the interrupt reset it * before proceeding with cleanup. */ - ath10k_pci_warm_reset(ar); + ath10k_pci_safe_chip_reset(ar); ath10k_pci_irq_disable(ar); ath10k_pci_irq_sync(ar); @@ -2102,6 +2125,18 @@ static int ath10k_pci_warm_reset(struct ath10k *ar) return 0; } +static int ath10k_pci_safe_chip_reset(struct ath10k *ar) +{ + if (QCA_REV_988X(ar) || QCA_REV_6174(ar)) { + return ath10k_pci_warm_reset(ar); + } else if (QCA_REV_99X0(ar)) { + ath10k_pci_irq_disable(ar); + return ath10k_pci_qca99x0_chip_reset(ar); + } else { + return -ENOTSUPP; + } +} + static int ath10k_pci_qca988x_chip_reset(struct ath10k *ar) { int i, ret; @@ -2208,12 +2243,38 @@ static int ath10k_pci_qca6174_chip_reset(struct ath10k *ar) return 0; } +static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar) +{ + int ret; + + ath10k_dbg(ar, ATH10K_DBG_BOOT, boot qca99x0 chip reset\n); + + ret = ath10k_pci_cold_reset(ar); + if (ret) { + ath10k_warn(ar, failed to cold reset: %d\n, ret); + return ret; + } + + ret = ath10k_pci_wait_for_target_init(ar); + if (ret) { + ath10k_warn(ar, failed to wait for target after cold reset: %d\n, + ret); + return ret
[PATCH 00/10] Add QCA99X0 support
This patch set adds changes for QCA99X0 chip in pci probe, Copy Engine init and firmware downloads. Since it is still work in progress the support for this chip is not yet advertised in pci device table. Vasanthakumar Thiagarajan (10): ath10k: Add a table to store hw specific values ath10k: Add new reg_address/mask to hw register table ath10k: Add hw register/values for QCA99X0 chip ath10k: Copy Engine related changes for QCA99X0 ath10k: Make target cpu address to CE address conversion chip specific ath10k: Add chip reset sequence for QCA99X0 ath10k: Extend CE src desc flags for interrupt indication ath10k: Fix BMI communication timeout for QCA99X0 ath10k: Add support for code swap ath10k: Add BMI param value to execute otp to hw_param drivers/net/wireless/ath/ath10k/Makefile| 3 +- drivers/net/wireless/ath/ath10k/bmi.h | 2 +- drivers/net/wireless/ath/ath10k/ce.c| 1 + drivers/net/wireless/ath/ath10k/ce.h| 17 ++- drivers/net/wireless/ath/ath10k/core.c | 52 ++- drivers/net/wireless/ath/ath10k/core.h | 9 ++ drivers/net/wireless/ath/ath10k/hw.c| 86 +++- drivers/net/wireless/ath/ath10k/hw.h| 61 ++-- drivers/net/wireless/ath/ath10k/pci.c | 180 ++-- drivers/net/wireless/ath/ath10k/pci.h | 12 -- drivers/net/wireless/ath/ath10k/swap.c | 208 drivers/net/wireless/ath/ath10k/swap.h | 72 ++ drivers/net/wireless/ath/ath10k/targaddrs.h | 3 + 13 files changed, 659 insertions(+), 47 deletions(-) create mode 100644 drivers/net/wireless/ath/ath10k/swap.c create mode 100644 drivers/net/wireless/ath/ath10k/swap.h -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/10] ath10k: Add new reg_address/mask to hw register table
Add more register address and mask which can be different for newer chip to hw_reg table. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/ce.h | 6 -- drivers/net/wireless/ath/ath10k/hw.c | 22 ++ drivers/net/wireless/ath/ath10k/hw.h | 17 - 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 0eddb20..93939de 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -423,8 +423,10 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) (nentries_mask)) -#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 -#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0xff00 +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \ + ar-regs-ce_wrap_intr_sum_host_msi_lsb +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK \ + ar-regs-ce_wrap_intr_sum_host_msi_mask #define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(x) \ (((x) CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) \ CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 48bcd2c..cb09867 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -34,8 +34,15 @@ const struct ath10k_hw_regs qca988x_regs = { .ce7_base_address = 0x00059000, .soc_reset_control_si0_rst_mask = 0x0001, .soc_reset_control_ce_rst_mask = 0x0004, - .soc_chip_id_address= 0x00ec, - .scratch_3_address = 0x0030, + .soc_chip_id_address= 0x00ec, + .scratch_3_address = 0x0030, + .fw_indicator_address = 0x9030, + .pcie_local_base_address= 0x0008, + .ce_wrap_intr_sum_host_msi_lsb = 0x0008, + .ce_wrap_intr_sum_host_msi_mask = 0xff00, + .pcie_intr_fw_mask = 0x0400, + .pcie_intr_ce_mask_all = 0x0007f800, + .pcie_intr_clr_address = 0x0014, }; const struct ath10k_hw_regs qca6174_regs = { @@ -54,8 +61,15 @@ const struct ath10k_hw_regs qca6174_regs = { .ce7_base_address = 0x00036000, .soc_reset_control_si0_rst_mask = 0x, .soc_reset_control_ce_rst_mask = 0x0001, - .soc_chip_id_address= 0x000f0, - .scratch_3_address = 0x0028, + .soc_chip_id_address= 0x00f0, + .scratch_3_address = 0x0028, + .fw_indicator_address = 0x9028, + .pcie_local_base_address= 0x0008, + .ce_wrap_intr_sum_host_msi_lsb = 0x0008, + .ce_wrap_intr_sum_host_msi_mask = 0xff00, + .pcie_intr_fw_mask = 0x0400, + .pcie_intr_ce_mask_all = 0x0007f800, + .pcie_intr_clr_address = 0x0014, }; const struct ath10k_hw_values qca988x_values = { diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index b218388..5d04317 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -164,6 +164,13 @@ struct ath10k_hw_regs { u32 soc_reset_control_ce_rst_mask; u32 soc_chip_id_address; u32 scratch_3_address; + u32 fw_indicator_address; + u32 pcie_local_base_address; + u32 ce_wrap_intr_sum_host_msi_lsb; + u32 ce_wrap_intr_sum_host_msi_mask; + u32 pcie_intr_fw_mask; + u32 pcie_intr_ce_mask_all; + u32 pcie_intr_clr_address; }; extern const struct ath10k_hw_regs qca988x_regs; @@ -386,7 +393,7 @@ enum ath10k_hw_rate_cck { #define CE7_BASE_ADDRESS ar-regs-ce7_base_address #define DBI_BASE_ADDRESS 0x0006 #define WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x0006c000 -#define PCIE_LOCAL_BASE_ADDRESS0x0008 +#define PCIE_LOCAL_BASE_ADDRESS ar-regs-pcie_local_base_address #define SOC_RESET_CONTROL_ADDRESS 0x #define SOC_RESET_CONTROL_OFFSET 0x @@ -460,7 +467,7 @@ enum ath10k_hw_rate_cck { #define CORE_CTRL_ADDRESS 0x #define PCIE_INTR_ENABLE_ADDRESS 0x0008 #define PCIE_INTR_CAUSE_ADDRESS0x000c -#define PCIE_INTR_CLR_ADDRESS 0x0014 +#define PCIE_INTR_CLR_ADDRESS ar-regs-pcie_intr_clr_address #define SCRATCH_3_ADDRESS ar-regs
[PATCH 05/10] ath10k: Make target cpu address to CE address conversion chip specific
Make the helper converting target virtual address space to CE address space a target type specific to support QCA99X0. Also make this as function instead of macro. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/pci.c | 25 ++--- drivers/net/wireless/ath/ath10k/pci.h | 12 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 980390a..422232c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -743,6 +743,26 @@ static void ath10k_pci_rx_replenish_retry(unsigned long ptr) ath10k_pci_rx_post(ar); } +static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) +{ + u32 val = 0; + + switch (ar-hw_rev) { + case ATH10K_HW_QCA988X: + case ATH10K_HW_QCA6174: + val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + CORE_CTRL_ADDRESS) + 0x7fff) 21; + break; + case ATH10K_HW_QCA99X0: + val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); + break; + } + + val |= 0x10 | (addr 0xf); + return val; +} + /* * Diagnostic read/write access is provided for startup/config/debug usage. * Caller must guarantee proper alignment, when applicable, and single user @@ -805,8 +825,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, * convert it from Target CPU virtual address space * to CE address space */ - address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci-mem, -address); + address = ath10k_pci_targ_cpu_to_ce_addr(ar, address); ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0, 0); @@ -964,7 +983,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, * to *CE address space */ - address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci-mem, address); + address = ath10k_pci_targ_cpu_to_ce_addr(ar, address); remaining_bytes = orig_nbytes; ce_data = ce_data_base; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index d7696dd..67f8d07 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -236,18 +236,6 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) #define CDC_WAR_MAGIC_STR 0xceef #define CDC_WAR_DATA_CE 4 -/* - * TODO: Should be a function call specific to each Target-type. - * This convoluted macro converts from Target CPU Virtual Address Space to CE - * Address Space. As part of this process, we conservatively fetch the current - * PCIE_BAR. MOST of the time, this should match the upper bits of PCI space - * for this device; but that's not guaranteed. - */ -#define TARG_CPU_SPACE_TO_CE_SPACE(ar, pci_addr, addr) \ - (((ath10k_pci_read32(ar, (SOC_CORE_BASE_ADDRESS | \ - CORE_CTRL_ADDRESS)) 0x7ff) 21) | \ -0x10 | ((addr) 0xf)) - /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */ #define DIAG_ACCESS_CE_TIMEOUT_MS 10 -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe linux-wireless in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 04/10] ath10k: Copy Engine related changes for QCA99X0
QCA99X0 supports upto 12 Copy engines. Host and target CE configuration table is updated to support new copy engine pipes. This also fixes the assumption of diagnostic CE by making CE_7 as the one instead of CE_COUNT - 1. Signed-off-by: Vasanthakumar Thiagarajan vthia...@qti.qualcomm.com --- drivers/net/wireless/ath/ath10k/ce.h | 2 +- drivers/net/wireless/ath/ath10k/hw.h | 3 ++ drivers/net/wireless/ath/ath10k/pci.c | 69 ++- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 93939de..bb4b8f3 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -21,7 +21,7 @@ #include hif.h /* Maximum number of Copy Engine's supported */ -#define CE_COUNT_MAX 8 +#define CE_COUNT_MAX 12 #define CE_HTT_H2T_MSG_SRC_NENTRIES 4096 /* Descriptor rings must be aligned to this boundary */ diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 76caeab..5819659 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -343,6 +343,9 @@ enum ath10k_hw_rate_cck { #define TARGET_TLV_NUM_MSDU_DESC (1024 + 32) #define TARGET_TLV_NUM_WOW_PATTERNS22 +/* Diagnostic Window */ +#define CE_DIAG_PIPE 7 + #define NUM_TARGET_CE_CONFIG_WLAN ar-hw_values-num_target_ce_config_wlan /* Number of Copy Engines supported */ diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 190f7f3..980390a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -156,6 +156,38 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_sz_max = DIAG_TRANSFER_LIMIT, .dest_nentries = 2, }, + + /* CE8: target-host pktlog */ + { + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 2048, + .dest_nentries = 128, + }, + + /* CE9 target autonomous qcache memcpy */ + { + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 0, + .dest_nentries = 0, + }, + + /* CE10: target autonomous hif memcpy */ + { + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 0, + .dest_nentries = 0, + }, + + /* CE11: target autonomous hif memcpy */ + { + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 0, + .dest_nentries = 0, + }, }; /* Target firmware's Copy Engine configuration. */ @@ -233,6 +265,38 @@ static const struct ce_pipe_config target_ce_config_wlan[] = { }, /* CE7 used only by Host */ + { + .pipenum = __cpu_to_le32(7), + .pipedir = __cpu_to_le32(PIPEDIR_INOUT), + .nentries = __cpu_to_le32(0), + .nbytes_max = __cpu_to_le32(0), + .flags = __cpu_to_le32(0), + .reserved = __cpu_to_le32(0), + }, + + /* CE8 target-host packtlog */ + { + .pipenum = __cpu_to_le32(8), + .pipedir = __cpu_to_le32(PIPEDIR_IN), + .nentries = __cpu_to_le32(64), + .nbytes_max = __cpu_to_le32(2048), + .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR), + .reserved = __cpu_to_le32(0), + }, + + /* CE9 target autonomous qcache memcpy */ + { + .pipenum = __cpu_to_le32(9), + .pipedir = __cpu_to_le32(PIPEDIR_INOUT), + .nentries = __cpu_to_le32(32), + .nbytes_max = __cpu_to_le32(2048), + .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR), + .reserved = __cpu_to_le32(0), + }, + + /* It not necessary to send target wlan configuration for CE10 CE11 +* as these CEs are not actively used in target. +*/ }; /* @@ -1759,7 +1823,8 @@ static int ath10k_pci_init_config(struct ath10k *ar) ret = ath10k_pci_diag_write_mem(ar, pipe_cfg_targ_addr, target_ce_config_wlan, - sizeof(target_ce_config_wlan)); + sizeof(struct ce_pipe_config) * + NUM_TARGET_CE_CONFIG_WLAN); if (ret != 0) { ath10k_err(ar, Failed to write pipe cfg: %d\n, ret); @@ -1873,7 +1938,7 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar) } /* Last CE is Diagnostic Window */ - if (i == CE_COUNT - 1) { + if (i == CE_DIAG_PIPE) { ar_pci-ce_diag = pipe-ce_hdl; continue