Re: ath9k driver may be broken on ARM64 ?
Dominique Martinet wrote on Thu, Oct 25, 2018: > What I find surprising is that the mapping for sc->mem is done (as shown > in the kernel page table dump), and some REG_WRITE worked before, but > the first REG_READ fails despite being an aligned address so something > is odd with how the memory is setup? > > > I think it would be interesting to add some debug statement early in > init (pci init to check how the memory is setup, if I'm not wrong about > it being pci, and along the path I described earlier) ; but my free time > ended long ago so don't think I'll be of much more use from now :p (not sure if you got notified off list, but fwiw the bug is apparently resolved by upgrading to a newer release of u-boot - same version, from u-boot 2017.03 armada v17.06 to u-boot 2017.03 armada v17.10 I have no idea what they're doing in u-boot with the memory setup but I guess the case is closed...) -- Asmadeus | Dominique Martinet
[PATCH v2] ath10k: report tx rate using ieee80211_tx_rate_update()
Mesh path metric needs tx rate information from ieee80211_tx_status() call but in ath10k there is no mechanism to report tx rate information via ieee80211_tx_status(), the tx rate is only accessible via sta_statiscs() op. Per peer tx stats has tx rate info available, Tx rate is available to ath10k driver after every 4 PPDU sent in the air. For each PPDU, ath10k driver updates rate informattion to mac80211 using ieee80211_tx_rate_update(). Per peer txrate information is updated through per peer statistics and is available for QCA9888/QCA9984/QCA4019/QCA998X only Tested on QCA9984 with firmware-5.bin_10.4-3.5.3-00053 Tested on QCA998X with firmware-5.bin_10.2.4-1.0-00036 Signed-off-by: Anilkumar Kolli --- V2: - Rebased on top of tree - Dependency mac80211 patch got merged drivers/net/wireless/ath/ath10k/core.h |1 + drivers/net/wireless/ath/ath10k/htt_rx.c | 67 +++--- drivers/net/wireless/ath/ath10k/wmi.h|1 + 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 042418097cf9..6fb3944fb76a 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -493,6 +493,7 @@ struct ath10k_sta { u32 smps; u16 peer_id; struct rate_info txrate; + struct ieee80211_tx_info tx_info; struct work_struct update_wk; u64 rx_duration; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index ffec98f7be50..6a41b4144f01 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2627,7 +2627,7 @@ void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) dev_kfree_skb_any(skb); } -static inline int ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate) +static inline s8 ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate) { static const u8 legacy_rates[] = {1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54}; @@ -2646,7 +2646,7 @@ static inline int ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate) ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, struct ath10k_sta *arsta, struct ath10k_per_peer_tx_stats *pstats, - u8 legacy_rate_idx) + s8 legacy_rate_idx) { struct rate_info *txrate = &arsta->txrate; struct ath10k_htt_tx_stats *tx_stats; @@ -2751,8 +2751,10 @@ static inline int ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate) struct ath10k_per_peer_tx_stats *peer_stats) { struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; + struct ieee80211_chanctx_conf *conf = NULL; u8 rate = 0, sgi; s8 rate_idx = 0; + bool skip_auto_rate; struct rate_info txrate; lockdep_assert_held(&ar->data_lock); @@ -2762,6 +2764,13 @@ static inline int ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate) txrate.nss = ATH10K_HW_NSS(peer_stats->ratecode); txrate.mcs = ATH10K_HW_MCS_RATE(peer_stats->ratecode); sgi = ATH10K_HW_GI(peer_stats->flags); + skip_auto_rate = ATH10K_FW_SKIPPED_RATE_CTRL(peer_stats->flags); + + /* Firmware's rate control skips broadcast/management frames, +* if host has configure fixed rates and in some other special cases. +*/ + if (skip_auto_rate) + return; if (txrate.flags == WMI_RATE_PREAMBLE_VHT && txrate.mcs > 9) { ath10k_warn(ar, "Invalid VHT mcs %hhd peer stats", txrate.mcs); @@ -2776,7 +2785,7 @@ static inline int ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate) } memset(&arsta->txrate, 0, sizeof(arsta->txrate)); - + memset(&arsta->tx_info.status, 0, sizeof(arsta->tx_info.status)); if (txrate.flags == WMI_RATE_PREAMBLE_CCK || txrate.flags == WMI_RATE_PREAMBLE_OFDM) { rate = ATH10K_HW_LEGACY_RATE(peer_stats->ratecode); @@ -2795,11 +2804,59 @@ static inline int ath10k_get_legacy_rate_idx(struct ath10k *ar, u8 rate) arsta->txrate.mcs = txrate.mcs; } - if (sgi) - arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + switch (txrate.flags) { + case WMI_RATE_PREAMBLE_OFDM: + if (arsta->arvif && arsta->arvif->vif) + conf = rcu_dereference(arsta->arvif->vif->chanctx_conf); + if (conf && conf->def.chan->band == NL80211_BAND_5GHZ) + arsta->tx_info.status.rates[0].idx = rate_idx - 4; + break; + case WMI_RATE_PREAMBLE_CCK: + arsta->tx_info.status.rates[0].idx = rate_idx; + if (sgi) + arsta->tx_info.status.rates[0
Re: [PATCH] mac80211: support FTM responder configuration/statistics
I just realized that this is broken in nl80211_channel_switch() and ieee80211_set_csa_beacon(), doing a CSA will always disable FTM unless it was actually included in the new configuration. Hi Johannes oops..Yes, there is a bug in the patch. The code below, I think, must fix this issue. Please let me know your comments.. diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 51622333d460..70d6de29425b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2934,19 +2934,20 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); pos += beacon->probe_resp_len; } - if (beacon->ftm_responder) + if (beacon->ftm_responder != -1) { new_beacon->ftm_responder = beacon->ftm_responder; - if (beacon->lci) { - new_beacon->lci_len = beacon->lci_len; - new_beacon->lci = pos; - memcpy(pos, beacon->lci, beacon->lci_len); - pos += beacon->lci_len; - } - if (beacon->civicloc) { - new_beacon->civicloc_len = beacon->civicloc_len; - new_beacon->civicloc = pos; - memcpy(pos, beacon->civicloc, beacon->civicloc_len); - pos += beacon->civicloc_len; + if (beacon->lci) { + new_beacon->lci_len = beacon->lci_len; + new_beacon->lci = pos; + memcpy(pos, beacon->lci, beacon->lci_len); + pos += beacon->lci_len; + } + if (beacon->civicloc) { + new_beacon->civicloc_len = beacon->civicloc_len; + new_beacon->civicloc = pos; + memcpy(pos, beacon->civicloc, beacon->civicloc_len); + pos += beacon->civicloc_len; + } } return new_beacon; Doing the trivial thing: memset(¶ms, 0, sizeof(params)); + params.beacon_after.ftm_responder = -1; This would not be needed then. in nl80211_channel_switch() will not help because then mac80211 will lose all the extra configuration, and will actually store -1 into its enabled value which is really strange. I'd appreciate if you could take a look at this. Thanks, johannes
[PATCH v2 3/3] {nl,mac}80211: add dot11MeshConnectedToMeshGate to meshconf
When userspace is controlling mesh routing, it may have better knowledge about whether a mesh STA is connected to a mesh gate than the kernel mpath table. Add dot11MeshConnectedToMeshGate to the mesh config so that such applications can explicitly signal that a mesh STA is connected to a gate, which will then be advertised in the beacon. Signed-off-by: Bob Copeland --- v2: add policy range and type comment include/net/cfg80211.h| 5 + include/uapi/linux/nl80211.h | 8 +++- net/mac80211/cfg.c| 3 +++ net/mac80211/debugfs_netdev.c | 3 +++ net/mac80211/mesh.c | 3 ++- net/wireless/nl80211.c| 8 +++- 6 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f2cb1a3c9651..cddaa9dacb27 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1562,6 +1562,10 @@ struct bss_parameters { * @plink_timeout: If no tx activity is seen from a STA we've established * peering with for longer than this time (in seconds), then remove it * from the STA's list of peers. Default is 30 minutes. + * @dot11MeshConnectedToMeshGate: if set to true, advertise that this STA is + * connected to a mesh gate in mesh formation info. If false, the + * value in mesh formation is determined by the presence of root paths + * in the mesh path table */ struct mesh_config { u16 dot11MeshRetryTimeout; @@ -1581,6 +1585,7 @@ struct mesh_config { u16 dot11MeshHWMPperrMinInterval; u16 dot11MeshHWMPnetDiameterTraversalTime; u8 dot11MeshHWMPRootMode; + bool dot11MeshConnectedToMeshGate; u16 dot11MeshHWMPRannInterval; bool dot11MeshGateAnnouncementProtocol; bool dot11MeshForwarding; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f2d79f9b4b5a..ba0dc0afdc29 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3075,7 +3075,7 @@ enum nl80211_sta_bss_param { * some packets with an FCS error due to TA corruption. Hence this counter * might not be fully accurate. * @NL80211_STA_INFO_CONNECTED_TO_GATE: set to true if STA has a path to a - * mesh gate + * mesh gate (u8, 0 or 1) * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -3898,6 +3898,11 @@ enum nl80211_mesh_power_mode { * remove it from the STA's list of peers. You may set this to 0 to disable * the removal of the STA. Default is 30 minutes. * + * @NL80211_MESHCONF_CONNECTED_TO_GATE: If set to true then this mesh STA + * will advertise that it is connected to a gate in the mesh formation + * field. If left unset then the mesh formation field will only + * advertise such if there is an active root mesh path. + * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use */ enum nl80211_meshconf_params { @@ -3930,6 +3935,7 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_POWER_MODE, NL80211_MESHCONF_AWAKE_WINDOW, NL80211_MESHCONF_PLINK_TIMEOUT, + NL80211_MESHCONF_CONNECTED_TO_GATE, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 51622333d460..6d1c54f28df7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2028,6 +2028,9 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, nconf->dot11MeshAwakeWindowDuration; if (_chg_mesh_attr(NL80211_MESHCONF_PLINK_TIMEOUT, mask)) conf->plink_timeout = nconf->plink_timeout; + if (_chg_mesh_attr(NL80211_MESHCONF_CONNECTED_TO_GATE, mask)) + conf->dot11MeshConnectedToMeshGate = + nconf->dot11MeshConnectedToMeshGate; ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON); return 0; } diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index c813207bb123..cff0fb3578c9 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -641,6 +641,8 @@ IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval, IEEE80211_IF_FILE(power_mode, u.mesh.mshcfg.power_mode, DEC); IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration, u.mesh.mshcfg.dot11MeshAwakeWindowDuration, DEC); +IEEE80211_IF_FILE(dot11MeshConnectedToMeshGate, + u.mesh.mshcfg.dot11MeshConnectedToMeshGate, DEC); #endif #define DEBUGFS_ADD_MODE(name, mode) \ @@ -762,6 +764,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval); MESHPARAMS_ADD(power_mode); MESHPARAMS_ADD(dot11MeshAwakeWindowDuration); + MESHPARAMS_ADD(dot11MeshConnectedToMeshGate); #undef MESHPARAMS_ADD } #endif diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 19205c821dee..4869280a6413 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.
[PATCH 4/4] staging: wilc1000: Remove unused mutex cfg_values_lock
After removing cfg_values member, cfg_values_lock that was used to protect it can also be removed. Signed-off-by: Adham Abozaeid --- drivers/staging/wilc1000/host_interface.c | 9 - drivers/staging/wilc1000/host_interface.h | 2 -- 2 files changed, 11 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index cdc495287949..165330b494f5 100755 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -369,11 +369,8 @@ static void handle_cfg_param(struct work_struct *work) struct cfg_param_attr *param = &msg->body.cfg_info; int ret; struct wid wid_list[32]; - struct host_if_drv *hif_drv = vif->hif_drv; int i = 0; - mutex_lock(&hif_drv->cfg_values_lock); - if (param->flag & RETRY_SHORT) { wid_list[i].id = WID_SHORT_RETRY_LIMIT; wid_list[i].val = (s8 *)¶m->short_retry_limit; @@ -409,7 +406,6 @@ static void handle_cfg_param(struct work_struct *work) if (ret) netdev_err(vif->ndev, "Error in setting CFG params\n"); - mutex_unlock(&hif_drv->cfg_values_lock); kfree(msg); } @@ -3123,15 +3119,10 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0); timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0); - mutex_init(&hif_drv->cfg_values_lock); - mutex_lock(&hif_drv->cfg_values_lock); - hif_drv->hif_state = HOST_IF_IDLE; hif_drv->p2p_timeout = 0; - mutex_unlock(&hif_drv->cfg_values_lock); - wilc->clients_count++; return 0; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 60cb1a1fee1a..c78e0682a248 100755 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -238,8 +238,6 @@ struct host_if_drv { enum host_if_state hif_state; u8 assoc_bssid[ETH_ALEN]; - /*lock to protect concurrent setting of cfg params*/ - struct mutex cfg_values_lock; struct timer_list scan_timer; struct wilc_vif *scan_timer_vif; -- 2.17.1
[PATCH 0/4] staging: wilc1000: validate input to set_wiphy_param and return proper errors
Validate input parameters to set_wiphy_param before scheduling handle_cfg_param() to validate them. This way proper errors can be returned to caller. Also cleaned up unused code in handle_cfg_param. Adham Abozaeid (4): staging: wilc1000: remove unused flags in handle_cfg_param() stagign: wilc1000: validate cfg parameters before scheduling the work staging: wilc1000: Don't keep a copy of wiphy parameters in the driver staging: wilc1000: Remove unused mutex cfg_values_lock drivers/staging/wilc1000/host_interface.c | 291 +- drivers/staging/wilc1000/host_interface.h | 32 -- .../staging/wilc1000/wilc_wfi_cfgoperations.c | 50 ++- drivers/staging/wilc1000/wilc_wlan_if.h | 9 - 4 files changed, 58 insertions(+), 324 deletions(-) mode change 100644 => 100755 drivers/staging/wilc1000/host_interface.c mode change 100644 => 100755 drivers/staging/wilc1000/host_interface.h mode change 100644 => 100755 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c mode change 100644 => 100755 drivers/staging/wilc1000/wilc_wlan_if.h -- 2.17.1
[PATCH 3/4] staging: wilc1000: Don't keep a copy of wiphy parameters in the driver
host_if_drv.cfg_values is a write only member, and can be removed Signed-off-by: Adham Abozaeid --- drivers/staging/wilc1000/host_interface.c | 13 - drivers/staging/wilc1000/host_interface.h | 1 - 2 files changed, 14 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0bb3b4f6d04e..cdc495287949 100755 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -375,43 +375,31 @@ static void handle_cfg_param(struct work_struct *work) mutex_lock(&hif_drv->cfg_values_lock); if (param->flag & RETRY_SHORT) { - u16 retry_limit = param->short_retry_limit; - wid_list[i].id = WID_SHORT_RETRY_LIMIT; wid_list[i].val = (s8 *)¶m->short_retry_limit; wid_list[i].type = WID_SHORT; wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.short_retry_limit = retry_limit; i++; } if (param->flag & RETRY_LONG) { - u16 limit = param->long_retry_limit; - wid_list[i].id = WID_LONG_RETRY_LIMIT; wid_list[i].val = (s8 *)¶m->long_retry_limit; wid_list[i].type = WID_SHORT; wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.long_retry_limit = limit; i++; } if (param->flag & FRAG_THRESHOLD) { - u16 frag_th = param->frag_threshold; - wid_list[i].id = WID_FRAG_THRESHOLD; wid_list[i].val = (s8 *)¶m->frag_threshold; wid_list[i].type = WID_SHORT; wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.frag_threshold = frag_th; i++; } if (param->flag & RTS_THRESHOLD) { - u16 rts_th = param->rts_threshold; - wid_list[i].id = WID_RTS_THRESHOLD; wid_list[i].val = (s8 *)¶m->rts_threshold; wid_list[i].type = WID_SHORT; wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.rts_threshold = rts_th; i++; } @@ -3139,7 +3127,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) mutex_lock(&hif_drv->cfg_values_lock); hif_drv->hif_state = HOST_IF_IDLE; - hif_drv->cfg_values.scan_source = DEFAULT_SCAN; hif_drv->p2p_timeout = 0; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5f894fe7c896..60cb1a1fee1a 100755 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -238,7 +238,6 @@ struct host_if_drv { enum host_if_state hif_state; u8 assoc_bssid[ETH_ALEN]; - struct cfg_param_attr cfg_values; /*lock to protect concurrent setting of cfg params*/ struct mutex cfg_values_lock; -- 2.17.1
[PATCH 1/4] staging: wilc1000: remove unused flags in handle_cfg_param()
handle_cfg_param() receives a bit map that describes what to be changed. Some of these bits flags aren't referred to from elsewhere and can be removed. Signed-off-by: Adham Abozaeid --- drivers/staging/wilc1000/host_interface.c | 216 -- drivers/staging/wilc1000/host_interface.h | 29 --- drivers/staging/wilc1000/wilc_wlan_if.h | 9 - 3 files changed, 254 deletions(-) mode change 100644 => 100755 drivers/staging/wilc1000/host_interface.c mode change 100644 => 100755 drivers/staging/wilc1000/host_interface.h mode change 100644 => 100755 drivers/staging/wilc1000/wilc_wlan_if.h diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c old mode 100644 new mode 100755 index 01db8999335e..1a1ac5e936a7 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -374,64 +374,6 @@ static void handle_cfg_param(struct work_struct *work) mutex_lock(&hif_drv->cfg_values_lock); - if (param->flag & BSS_TYPE) { - u8 bss_type = param->bss_type; - - if (bss_type < 6) { - wid_list[i].id = WID_BSS_TYPE; - wid_list[i].val = (s8 *)¶m->bss_type; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.bss_type = bss_type; - } else { - netdev_err(vif->ndev, "check value 6 over\n"); - goto unlock; - } - i++; - } - if (param->flag & AUTH_TYPE) { - u8 auth_type = param->auth_type; - - if (auth_type == 1 || auth_type == 2 || auth_type == 5) { - wid_list[i].id = WID_AUTH_TYPE; - wid_list[i].val = (s8 *)¶m->auth_type; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.auth_type = auth_type; - } else { - netdev_err(vif->ndev, "Impossible value\n"); - goto unlock; - } - i++; - } - if (param->flag & AUTHEN_TIMEOUT) { - if (param->auth_timeout > 0) { - wid_list[i].id = WID_AUTH_TIMEOUT; - wid_list[i].val = (s8 *)¶m->auth_timeout; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.auth_timeout = param->auth_timeout; - } else { - netdev_err(vif->ndev, "Range(1 ~ 65535) over\n"); - goto unlock; - } - i++; - } - if (param->flag & POWER_MANAGEMENT) { - u8 pm_mode = param->power_mgmt_mode; - - if (pm_mode < 5) { - wid_list[i].id = WID_POWER_MANAGEMENT; - wid_list[i].val = (s8 *)¶m->power_mgmt_mode; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.power_mgmt_mode = pm_mode; - } else { - netdev_err(vif->ndev, "Invalid power mode\n"); - goto unlock; - } - i++; - } if (param->flag & RETRY_SHORT) { u16 retry_limit = param->short_retry_limit; @@ -492,160 +434,6 @@ static void handle_cfg_param(struct work_struct *work) } i++; } - if (param->flag & PREAMBLE) { - u16 preamble_type = param->preamble_type; - - if (param->preamble_type < 3) { - wid_list[i].id = WID_PREAMBLE; - wid_list[i].val = (s8 *)¶m->preamble_type; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.preamble_type = preamble_type; - } else { - netdev_err(vif->ndev, "Preamble Range(0~2) over\n"); - goto unlock; - } - i++; - } - if (param->flag & SHORT_SLOT_ALLOWED) { - u8 slot_allowed = param->short_slot_allowed; - - if (slot_allowed < 2) { - wid_list[i].id = WID_SHORT_SLOT_ALLOWED; - wid_list[i].val = (s8 *)¶m->short_slot_allowed; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.short_slot_allowed = slot_allowed; - } else { - netdev_err(vif->ndev, "Short slot(2) over\n"); - goto unlock; - } - i++; - } - i
[PATCH 2/4] stagign: wilc1000: validate cfg parameters before scheduling the work
Validate cfg parameters after being called by cfg80211 in set_wiphy_params before scheduling the work executed in handle_cfg_param Signed-off-by: Adham Abozaeid --- drivers/staging/wilc1000/host_interface.c | 61 ++- .../staging/wilc1000/wilc_wfi_cfgoperations.c | 50 --- 2 files changed, 62 insertions(+), 49 deletions(-) mode change 100644 => 100755 drivers/staging/wilc1000/wilc_wfi_cfgoperations.c diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 1a1ac5e936a7..0bb3b4f6d04e 100755 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -377,61 +377,41 @@ static void handle_cfg_param(struct work_struct *work) if (param->flag & RETRY_SHORT) { u16 retry_limit = param->short_retry_limit; - if (retry_limit > 0 && retry_limit < 256) { - wid_list[i].id = WID_SHORT_RETRY_LIMIT; - wid_list[i].val = (s8 *)¶m->short_retry_limit; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.short_retry_limit = retry_limit; - } else { - netdev_err(vif->ndev, "Range(1~256) over\n"); - goto unlock; - } + wid_list[i].id = WID_SHORT_RETRY_LIMIT; + wid_list[i].val = (s8 *)¶m->short_retry_limit; + wid_list[i].type = WID_SHORT; + wid_list[i].size = sizeof(u16); + hif_drv->cfg_values.short_retry_limit = retry_limit; i++; } if (param->flag & RETRY_LONG) { u16 limit = param->long_retry_limit; - if (limit > 0 && limit < 256) { - wid_list[i].id = WID_LONG_RETRY_LIMIT; - wid_list[i].val = (s8 *)¶m->long_retry_limit; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.long_retry_limit = limit; - } else { - netdev_err(vif->ndev, "Range(1~256) over\n"); - goto unlock; - } + wid_list[i].id = WID_LONG_RETRY_LIMIT; + wid_list[i].val = (s8 *)¶m->long_retry_limit; + wid_list[i].type = WID_SHORT; + wid_list[i].size = sizeof(u16); + hif_drv->cfg_values.long_retry_limit = limit; i++; } if (param->flag & FRAG_THRESHOLD) { u16 frag_th = param->frag_threshold; - if (frag_th > 255 && frag_th < 7937) { - wid_list[i].id = WID_FRAG_THRESHOLD; - wid_list[i].val = (s8 *)¶m->frag_threshold; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.frag_threshold = frag_th; - } else { - netdev_err(vif->ndev, "Threshold Range fail\n"); - goto unlock; - } + wid_list[i].id = WID_FRAG_THRESHOLD; + wid_list[i].val = (s8 *)¶m->frag_threshold; + wid_list[i].type = WID_SHORT; + wid_list[i].size = sizeof(u16); + hif_drv->cfg_values.frag_threshold = frag_th; i++; } if (param->flag & RTS_THRESHOLD) { u16 rts_th = param->rts_threshold; - if (rts_th > 255) { - wid_list[i].id = WID_RTS_THRESHOLD; - wid_list[i].val = (s8 *)¶m->rts_threshold; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.rts_threshold = rts_th; - } else { - netdev_err(vif->ndev, "Threshold Range fail\n"); - goto unlock; - } + wid_list[i].id = WID_RTS_THRESHOLD; + wid_list[i].val = (s8 *)¶m->rts_threshold; + wid_list[i].type = WID_SHORT; + wid_list[i].size = sizeof(u16); + hif_drv->cfg_values.rts_threshold = rts_th; i++; } @@ -441,7 +421,6 @@ static void handle_cfg_param(struct work_struct *work) if (ret) netdev_err(vif->ndev, "Error in setting CFG params\n"); -unlock: mutex_unlock(&hif_drv->cfg_values_lock); kfree(msg); } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c old mode 100644 new mode 100755 index 4fd5a64b..26bb78a49d81 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1149,21 +1149,55 @@ static int set_wiphy
Re: [PATCH AUTOSEL 3.18 13/98] PCI: Mark Atheros AR9580 to avoid bus reset
On 25/10/2018, Sasha Levin wrote: > From: Maik Broemme > > [ Upstream commit 8e2e03179923479ca0c0b6fdc7c93ecf89bce7a8 ] > > Similar to the AR93xx and the AR94xx series, the AR95xx also have the same > quirk for the Bus Reset. It will lead to instant system reset if the > device is assigned via VFIO to a KVM VM. I've been able reproduce this > behavior with a MikroTik R11e-2HnD. > > Fixes: c3e59ee4e766 ("PCI: Mark Atheros AR93xx to avoid bus reset") > Signed-off-by: Maik Broemme > Signed-off-by: Bjorn Helgaas > CC: sta...@vger.kernel.org# v3.14+ > Signed-off-by: Sasha Levin > --- > drivers/pci/quirks.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c > index 9e86ace95832..0b75b47a5329 100644 > --- a/drivers/pci/quirks.c > +++ b/drivers/pci/quirks.c > @@ -3081,6 +3081,7 @@ static void quirk_no_bus_reset(struct pci_dev *dev) > DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, > quirk_no_bus_reset); > DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, > quirk_no_bus_reset); > DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, > quirk_no_bus_reset); > +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, > quirk_no_bus_reset); > > #ifdef CONFIG_ACPI > /* > -- > 2.17.1 > > Hi You should CC this to linux-wireless list too
[PATCH 1/3] mac80211: mesh: advertise gates in mesh formation
The Connected to Mesh Gate subfield (802.11-2016 9.4.2.98.7) in the Mesh Formation Info field is currently unset. This field may be useful in determining which MBSSes to join or which mesh STAs to peer with. If this mesh STA is a gate, by having turned on mesh gate announcements, or if we have a path to one (e.g. by having received RANNs) then set this bit to 1. Signed-off-by: Bob Copeland --- net/mac80211/mesh.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 8bad414c52ad..19205c821dee 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -254,6 +254,8 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; u8 *pos, neighbors; u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie); + bool is_connected_to_gate = ifmsh->num_gates > 0 || + ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol; if (skb_tailroom(skb) < 2 + meshconf_len) return -ENOMEM; @@ -278,7 +280,7 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, /* Mesh Formation Info - number of neighbors */ neighbors = atomic_read(&ifmsh->estab_plinks); neighbors = min_t(int, neighbors, IEEE80211_MAX_MESH_PEERINGS); - *pos++ = neighbors << 1; + *pos++ = (neighbors << 1) | is_connected_to_gate; /* Mesh capability */ *pos = 0x00; *pos |= ifmsh->mshcfg.dot11MeshForwarding ? -- 2.11.0
[PATCH 2/3] {nl,mac}80211: report gate connectivity in station info
Capture the current state of gate connectivity from the mesh formation field in mesh config whenever we receive a beacon, and report that via GET_STATION. This allows applications doing mesh peering in userspace to make peering decisions based on peers' current upstream connectivity. Signed-off-by: Bob Copeland --- include/linux/ieee80211.h| 2 ++ include/net/cfg80211.h | 3 +++ include/uapi/linux/nl80211.h | 3 +++ net/mac80211/mesh_plink.c| 3 +++ net/mac80211/sta_info.c | 4 +++- net/mac80211/sta_info.h | 2 ++ net/wireless/nl80211.c | 1 + 7 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 0ef67f837ae1..407d6fd66fa9 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -812,6 +812,8 @@ enum mesh_config_capab_flags { IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL = 0x40, }; +#define IEEE80211_MESHCONF_FORM_CONNECTED_TO_GATE 0x1 + /** * mesh channel switch parameters element's flag indicator * diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1fa41b7a1be3..f2cb1a3c9651 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1296,6 +1296,7 @@ struct cfg80211_tid_stats { * @rx_beacon: number of beacons received from this peer * @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received * from this peer + * @connected_to_gate: true if mesh STA has a path to mesh gate * @rx_duration: aggregate PPDU duration(usecs) for all the frames from a peer * @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last * (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs. @@ -1350,6 +1351,8 @@ struct station_info { u64 rx_beacon; u64 rx_duration; u8 rx_beacon_signal_avg; + u8 connected_to_gate; + struct cfg80211_tid_stats *pertid; s8 ack_signal; s8 avg_ack_signal; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 6d610bae30a9..f2d79f9b4b5a 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3074,6 +3074,8 @@ enum nl80211_sta_bss_param { * with an FCS error (u32, from this station). This count may not include * some packets with an FCS error due to TA corruption. Hence this counter * might not be fully accurate. + * @NL80211_STA_INFO_CONNECTED_TO_GATE: set to true if STA has a path to a + * mesh gate * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -3116,6 +3118,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_ACK_SIGNAL_AVG, NL80211_STA_INFO_RX_MPDUS, NL80211_STA_INFO_FCS_ERROR_COUNT, + NL80211_STA_INFO_CONNECTED_TO_GATE, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 5b5b0f95ffd1..5f45a2b273df 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -590,6 +590,9 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, if (!sta) goto out; + sta->mesh->connected_to_gate = elems->mesh_config->meshconf_form & + IEEE80211_MESHCONF_FORM_CONNECTED_TO_GATE; + if (mesh_peer_accepts_plinks(elems) && sta->mesh->plink_state == NL80211_PLINK_LISTEN && sdata->u.mesh.accepting_plinks && diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index fb8c2252ac0e..971f06911ff8 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -2267,7 +2267,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, BIT_ULL(NL80211_STA_INFO_PLINK_STATE) | BIT_ULL(NL80211_STA_INFO_LOCAL_PM) | BIT_ULL(NL80211_STA_INFO_PEER_PM) | -BIT_ULL(NL80211_STA_INFO_NONPEER_PM); +BIT_ULL(NL80211_STA_INFO_NONPEER_PM) | +BIT_ULL(NL80211_STA_INFO_CONNECTED_TO_GATE); sinfo->llid = sta->mesh->llid; sinfo->plid = sta->mesh->plid; @@ -2279,6 +2280,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, sinfo->local_pm = sta->mesh->local_pm; sinfo->peer_pm = sta->mesh->peer_pm; sinfo->nonpeer_pm = sta->mesh->nonpeer_pm; + sinfo->connected_to_gate = sta->mesh->connected_to_gate; #endif } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 9a04327d71d1..8eb29041be54 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -364,6 +364,7 @@ DECLARE_EWMA(mesh_fail_avg, 20, 8) * @nonpeer_pm: STA power save mode towards non-peer neighbors * @processed_beacon: set to true after peer rates and capabilities are * processed + * @conn
[PATCH 3/3] {nl,mac}80211: add dot11MeshConnectedToMeshGate to meshconf
When userspace is controlling mesh routing, it may have better knowledge about whether a mesh STA is connected to a mesh gate than the kernel mpath table. Add dot11MeshConnectedToMeshGate to the mesh config so that such applications can explicitly signal that a mesh STA is connected to a gate, which will then be advertised in the beacon. Signed-off-by: Bob Copeland --- include/net/cfg80211.h| 5 + include/uapi/linux/nl80211.h | 6 ++ net/mac80211/cfg.c| 3 +++ net/mac80211/debugfs_netdev.c | 3 +++ net/mac80211/mesh.c | 3 ++- net/wireless/nl80211.c| 8 +++- 6 files changed, 26 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f2cb1a3c9651..cddaa9dacb27 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1562,6 +1562,10 @@ struct bss_parameters { * @plink_timeout: If no tx activity is seen from a STA we've established * peering with for longer than this time (in seconds), then remove it * from the STA's list of peers. Default is 30 minutes. + * @dot11MeshConnectedToMeshGate: if set to true, advertise that this STA is + * connected to a mesh gate in mesh formation info. If false, the + * value in mesh formation is determined by the presence of root paths + * in the mesh path table */ struct mesh_config { u16 dot11MeshRetryTimeout; @@ -1581,6 +1585,7 @@ struct mesh_config { u16 dot11MeshHWMPperrMinInterval; u16 dot11MeshHWMPnetDiameterTraversalTime; u8 dot11MeshHWMPRootMode; + bool dot11MeshConnectedToMeshGate; u16 dot11MeshHWMPRannInterval; bool dot11MeshGateAnnouncementProtocol; bool dot11MeshForwarding; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f2d79f9b4b5a..d04391ae4acd 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3898,6 +3898,11 @@ enum nl80211_mesh_power_mode { * remove it from the STA's list of peers. You may set this to 0 to disable * the removal of the STA. Default is 30 minutes. * + * @NL80211_MESHCONF_CONNECTED_TO_GATE: If set to true then this mesh STA + * will advertise that it is connected to a gate in the mesh formation + * field. If left unset then the mesh formation field will only + * advertise such if there is an active root mesh path. + * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use */ enum nl80211_meshconf_params { @@ -3930,6 +3935,7 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_POWER_MODE, NL80211_MESHCONF_AWAKE_WINDOW, NL80211_MESHCONF_PLINK_TIMEOUT, + NL80211_MESHCONF_CONNECTED_TO_GATE, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 51622333d460..6d1c54f28df7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2028,6 +2028,9 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, nconf->dot11MeshAwakeWindowDuration; if (_chg_mesh_attr(NL80211_MESHCONF_PLINK_TIMEOUT, mask)) conf->plink_timeout = nconf->plink_timeout; + if (_chg_mesh_attr(NL80211_MESHCONF_CONNECTED_TO_GATE, mask)) + conf->dot11MeshConnectedToMeshGate = + nconf->dot11MeshConnectedToMeshGate; ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON); return 0; } diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index c813207bb123..cff0fb3578c9 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -641,6 +641,8 @@ IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval, IEEE80211_IF_FILE(power_mode, u.mesh.mshcfg.power_mode, DEC); IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration, u.mesh.mshcfg.dot11MeshAwakeWindowDuration, DEC); +IEEE80211_IF_FILE(dot11MeshConnectedToMeshGate, + u.mesh.mshcfg.dot11MeshConnectedToMeshGate, DEC); #endif #define DEBUGFS_ADD_MODE(name, mode) \ @@ -762,6 +764,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval); MESHPARAMS_ADD(power_mode); MESHPARAMS_ADD(dot11MeshAwakeWindowDuration); + MESHPARAMS_ADD(dot11MeshConnectedToMeshGate); #undef MESHPARAMS_ADD } #endif diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 19205c821dee..4869280a6413 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -255,7 +255,8 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, u8 *pos, neighbors; u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie); bool is_connected_to_gate = ifmsh->num_gates > 0 || - ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol; + ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol || + ifmsh->mshcfg.dot11MeshConnectedToMeshGate; if (skb_tailr
[RFC][PATCH] wlcore: Fixup "Add support for optional wakeirq"
After commit 3c83dd577c7f ("wlcore: Add support for optional wakeirq") landed upstream, I started seeing the following oops on my HiKey board: [1.870279] Unable to handle kernel read from unreadable memory at virtual address 0010 [1.870283] Mem abort info: [1.870287] ESR = 0x9605 [1.870292] Exception class = DABT (current EL), IL = 32 bits [1.870296] SET = 0, FnV = 0 [1.870299] EA = 0, S1PTW = 0 [1.870302] Data abort info: [1.870306] ISV = 0, ISS = 0x0005 [1.870309] CM = 0, WnR = 0 [1.870312] [0010] user address but active_mm is swapper [1.870318] Internal error: Oops: 9605 [#1] PREEMPT SMP [1.870327] CPU: 0 PID: 5 Comm: kworker/0:0 Not tainted 4.19.0-05129-gb3d1e8e #48 [1.870331] Hardware name: HiKey Development Board (DT) [1.870350] Workqueue: events_freezable mmc_rescan [1.870358] pstate: 6045 (nZCv daif +PAN -UAO) [1.870366] pc : wl1271_probe+0x210/0x350 [1.870371] lr : wl1271_probe+0x210/0x350 [1.870374] sp : ff80080739b0 [1.870377] x29: ff80080739b0 x28: [1.870384] x27: x26: [1.870391] x25: 0036 x24: ffc074ecb598 [1.870398] x23: ffc07ffdce78 x22: ffc0744ed808 [1.870404] x21: ffc074ecbb98 x20: ff8008ff9000 [1.870411] x19: ffc0744ed800 x18: ff8008ff9a48 [1.870418] x17: x16: [1.870425] x15: ffc074ecb503 x14: [1.870431] x13: ffc074ecb502 x12: 0030 [1.870438] x11: 0101010101010101 x10: 0040 [1.870444] x9 : ffc075400248 x8 : ffc075400270 [1.870451] x7 : x6 : [1.870457] x5 : x4 : [1.870463] x3 : x2 : [1.870469] x1 : 0028 x0 : [1.870477] Process kworker/0:0 (pid: 5, stack limit = 0x(ptrval)) [1.870480] Call trace: [1.870485] wl1271_probe+0x210/0x350 [1.870491] sdio_bus_probe+0x100/0x128 [1.870500] really_probe+0x1a8/0x2b8 [1.870506] driver_probe_device+0x58/0x100 [1.870511] __device_attach_driver+0x94/0xd8 [1.870517] bus_for_each_drv+0x70/0xc8 [1.870522] __device_attach+0xe0/0x140 [1.870527] device_initial_probe+0x10/0x18 [1.870532] bus_probe_device+0x94/0xa0 [1.870537] device_add+0x374/0x5b8 [1.870542] sdio_add_func+0x60/0x88 [1.870546] mmc_attach_sdio+0x1b0/0x358 [1.870551] mmc_rescan+0x2cc/0x390 [1.870558] process_one_work+0x12c/0x320 [1.870563] worker_thread+0x48/0x458 [1.870569] kthread+0xf8/0x128 [1.870575] ret_from_fork+0x10/0x18 [1.870583] Code: 92400c21 b2760021 a90687a2 97e95bf9 (f9400803) [1.870587] ---[ end trace 1e15f81d3c139ca9 ]--- It seems since we don't have a wakeirq value in the dts, the wakeirq value in wl1271_probe() is zero, which then causes trouble in irqd_get_trigger_type(irq_get_irq_data(wakeirq)). This patch tries to address this by checking if wakeirq is zero, and not trying to add it to the resources if that is the case. Cc: Tony Lindgren Cc: Kalle Valo Cc: Eyal Reizer Cc: Anders Roxell Cc: linux-wireless@vger.kernel.org Acked-by: Tony Lindgren Signed-off-by: John Stultz --- drivers/net/wireless/ti/wlcore/sdio.c | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 4c2154b..bd10165 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -285,7 +285,7 @@ static int wl1271_probe(struct sdio_func *func, struct resource res[2]; mmc_pm_flag_t mmcflags; int ret = -ENOMEM; - int irq, wakeirq; + int irq, wakeirq, num_irqs; const char *chip_family; /* We are only able to handle the wlan function */ @@ -353,12 +353,17 @@ static int wl1271_probe(struct sdio_func *func, irqd_get_trigger_type(irq_get_irq_data(irq)); res[0].name = "irq"; - res[1].start = wakeirq; - res[1].flags = IORESOURCE_IRQ | - irqd_get_trigger_type(irq_get_irq_data(wakeirq)); - res[1].name = "wakeirq"; - ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); + if (wakeirq > 0) { + res[1].start = wakeirq; + res[1].flags = IORESOURCE_IRQ | + irqd_get_trigger_type(irq_get_irq_data(wakeirq)); + res[1].name = "wakeirq"; + num_irqs = 2; + } else { + num_irqs = 1; + } + ret = platform_device_add_resources(glue->core, res, num_irqs); if (ret) { dev_err(glue->dev, "can't add resources\n"); goto out_dev_put; -- 2.7.4
Re: [PATCH v3 1/2] mac80211_hwsim: allow setting iftype support
Johannes, Ping On Wed, 2018-10-17 at 14:16 -0700, James Prestwood wrote: > The mac80211_hwsim driver hard codes its supported interface types. > For > testing purposes it would be valuable to allow changing these > supported > types in order to simulate actual drivers that support a limited set > of > iftypes. A new attribute was added to allow this: > > - HWSIM_ATTR_IFTYPE_SUPPORT > A u32 bit field of supported NL80211_IFTYPE_* bits > > This will only enable/disable iftypes that mac80211_hwsim already > supports. > > In order to accomplish this, the ieee80211_iface_limit structure > needed > to be built dynamically to only include limit rules for iftypes that > the user requested to enable. > > Signed-off-by: James Prestwood > --- > drivers/net/wireless/mac80211_hwsim.c | 153 +++- > -- > drivers/net/wireless/mac80211_hwsim.h | 2 + > 2 files changed, 90 insertions(+), 65 deletions(-) > > diff --git a/drivers/net/wireless/mac80211_hwsim.c > b/drivers/net/wireless/mac80211_hwsim.c > index 18e819d964f1..2799eb247b7e 100644 > --- a/drivers/net/wireless/mac80211_hwsim.c > +++ b/drivers/net/wireless/mac80211_hwsim.c > @@ -448,48 +448,6 @@ static const struct nl80211_vendor_cmd_info > mac80211_hwsim_vendor_events[] = { > { .vendor_id = OUI_QCA, .subcmd = 1 }, > }; > > -static const struct ieee80211_iface_limit hwsim_if_limits[] = { > - { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, > - { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | > - BIT(NL80211_IFTYPE_P2P_CLIENT) | > -#ifdef CONFIG_MAC80211_MESH > - BIT(NL80211_IFTYPE_MESH_POINT) | > -#endif > - BIT(NL80211_IFTYPE_AP) | > - BIT(NL80211_IFTYPE_P2P_GO) }, > - /* must be last, see hwsim_if_comb */ > - { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) } > -}; > - > -static const struct ieee80211_iface_combination hwsim_if_comb[] = { > - { > - .limits = hwsim_if_limits, > - /* remove the last entry which is P2P_DEVICE */ > - .n_limits = ARRAY_SIZE(hwsim_if_limits) - 1, > - .max_interfaces = 2048, > - .num_different_channels = 1, > - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) > | > -BIT(NL80211_CHAN_WIDTH_20) | > -BIT(NL80211_CHAN_WIDTH_40) | > -BIT(NL80211_CHAN_WIDTH_80) | > -BIT(NL80211_CHAN_WIDTH_160), > - }, > -}; > - > -static const struct ieee80211_iface_combination > hwsim_if_comb_p2p_dev[] = { > - { > - .limits = hwsim_if_limits, > - .n_limits = ARRAY_SIZE(hwsim_if_limits), > - .max_interfaces = 2048, > - .num_different_channels = 1, > - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) > | > -BIT(NL80211_CHAN_WIDTH_20) | > -BIT(NL80211_CHAN_WIDTH_40) | > -BIT(NL80211_CHAN_WIDTH_80) | > -BIT(NL80211_CHAN_WIDTH_160), > - }, > -}; > - > static spinlock_t hwsim_radio_lock; > static LIST_HEAD(hwsim_radios); > static struct workqueue_struct *hwsim_wq; > @@ -513,6 +471,8 @@ struct mac80211_hwsim_data { > struct ieee80211_channel > channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; > struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; > struct ieee80211_iface_combination if_combination; > + struct ieee80211_iface_limit if_limits[3]; > + int n_if_limits; > > struct mac_address addresses[2]; > int channels, idx; > @@ -641,6 +601,7 @@ static const struct nla_policy > hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { > [HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG }, > [HWSIM_ATTR_FREQ] = { .type = NLA_U32 }, > [HWSIM_ATTR_PERM_ADDR] = { .type = NLA_UNSPEC, .len = ETH_ALEN > }, > + [HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 }, > }; > > static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, > @@ -2413,6 +2374,7 @@ struct hwsim_new_radio_params { > const char *hwname; > bool no_vif; > const u8 *perm_addr; > + u32 iftypes; > }; > > static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, > @@ -2517,6 +2479,29 @@ static void hwsim_mcast_new_radio(int id, > struct genl_info *info, > nlmsg_free(mcast_skb); > } > > +#ifdef CONFIG_MAC80211_MESH > +#define HWSIM_MESH_BIT BIT(NL80211_IFTYPE_MESH_POINT) > +#else > +#define HWSIM_MESH_BIT 0 > +#endif > + > +#define HWSIM_DEFAULT_IF_LIMIT \ > + ( \ > + BIT(NL80211_IFTYPE_STATION) | \ > + BIT(NL80211_IFTYPE_P2P_CLIENT) | \ > + BIT(NL80211_IFTYPE_AP) | \ > + BIT(NL80211_IFTYPE_P2P_GO) | \ > + HWSIM_MESH_BIT \ > + ) > + > +#define
Re: Regression: OOPs on boot due to "wlcore: Add support for optional wakeirq"
+ linux-wireless John Stultz writes: > On Thu, Oct 25, 2018 at 10:04 AM, John Stultz wrote: >> Hey Tony, >> In testing linus/master on my hikey board, I'm hitting the following >> OOPS on bootup: >> >> [1.870279] Unable to handle kernel read from unreadable memory at >> virtual address 0010 >> [1.870283] Mem abort info: >> [1.870287] ESR = 0x9605 >> [1.870292] Exception class = DABT (current EL), IL = 32 bits >> [1.870296] SET = 0, FnV = 0 >> [1.870299] EA = 0, S1PTW = 0 >> [1.870302] Data abort info: >> [1.870306] ISV = 0, ISS = 0x0005 >> [1.870309] CM = 0, WnR = 0 >> [1.870312] [0010] user address but active_mm is swapper >> [1.870318] Internal error: Oops: 9605 [#1] PREEMPT SMP >> [1.870327] CPU: 0 PID: 5 Comm: kworker/0:0 Not tainted >> 4.19.0-05129-gb3d1e8e #48 >> [1.870331] Hardware name: HiKey Development Board (DT) >> [1.870350] Workqueue: events_freezable mmc_rescan >> [1.870358] pstate: 6045 (nZCv daif +PAN -UAO) >> [1.870366] pc : wl1271_probe+0x210/0x350 >> [1.870371] lr : wl1271_probe+0x210/0x350 >> [1.870374] sp : ff80080739b0 >> [1.870377] x29: ff80080739b0 x28: >> [1.870384] x27: x26: >> [1.870391] x25: 0036 x24: ffc074ecb598 >> [1.870398] x23: ffc07ffdce78 x22: ffc0744ed808 >> [1.870404] x21: ffc074ecbb98 x20: ff8008ff9000 >> [1.870411] x19: ffc0744ed800 x18: ff8008ff9a48 >> [1.870418] x17: x16: >> [1.870425] x15: ffc074ecb503 x14: >> [1.870431] x13: ffc074ecb502 x12: 0030 >> [1.870438] x11: 0101010101010101 x10: 0040 >> [1.870444] x9 : ffc075400248 x8 : ffc075400270 >> [1.870451] x7 : x6 : >> [1.870457] x5 : x4 : >> [1.870463] x3 : x2 : >> [1.870469] x1 : 0028 x0 : >> [1.870477] Process kworker/0:0 (pid: 5, stack limit = 0x(ptrval)) >> [1.870480] Call trace: >> [1.870485] wl1271_probe+0x210/0x350 >> [1.870491] sdio_bus_probe+0x100/0x128 >> [1.870500] really_probe+0x1a8/0x2b8 >> [1.870506] driver_probe_device+0x58/0x100 >> [1.870511] __device_attach_driver+0x94/0xd8 >> [1.870517] bus_for_each_drv+0x70/0xc8 >> [1.870522] __device_attach+0xe0/0x140 >> [1.870527] device_initial_probe+0x10/0x18 >> [1.870532] bus_probe_device+0x94/0xa0 >> [1.870537] device_add+0x374/0x5b8 >> [1.870542] sdio_add_func+0x60/0x88 >> [1.870546] mmc_attach_sdio+0x1b0/0x358 >> [1.870551] mmc_rescan+0x2cc/0x390 >> [1.870558] process_one_work+0x12c/0x320 >> [1.870563] worker_thread+0x48/0x458 >> [1.870569] kthread+0xf8/0x128 >> [1.870575] ret_from_fork+0x10/0x18 >> [1.870583] Code: 92400c21 b2760021 a90687a2 97e95bf9 (f9400803) >> [1.870587] ---[ end trace 1e15f81d3c139ca9 ]--- >> >> >> I've bisected it down to 3c83dd577c7f ("wlcore: Add support for >> optional wakeirq"). >> >> It seems since we don't have a wakeirq value in the dts, the wakeirq >> value in wl1271_probe() is zero, which then causes trouble in >> irqd_get_trigger_type(irq_get_irq_data(wakeirq)). >> >> Should we check wakeirq before we set the second elements of res[]? > > Here's my first swing at doing the above. It seems to work ok. Let me > know if it looks reasonable and I'll submit it as a proper patch. > > https://git.linaro.org/people/john.stultz/android-dev.git/commit/?h=dev/hikey-mainline-WIP&id=383fb6e3abb71b8a721f196120a2e3a9da3315ac If you submit that remember to CC linux-wireless so that patchwork sees it. -- Kalle Valo
[PATCH 1/4] mt76: clean up more unused EXPORT_SYMBOLs
Make functions static where possible Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 9 + drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 1 - drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 1 - 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 4fb9f095ffec..34fc9f2eb51f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -128,7 +128,6 @@ void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop) if ((val & bit) != (bit * drop)) mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop)); } -EXPORT_SYMBOL_GPL(mt76x02_mac_wcid_set_drop); void mt76x02_txq_init(struct mt76x02_dev *dev, struct ieee80211_txq *txq) { @@ -220,7 +219,6 @@ void mt76x02_mac_set_short_preamble(struct mt76x02_dev *dev, bool enable) else mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT); } -EXPORT_SYMBOL_GPL(mt76x02_mac_set_short_preamble); bool mt76x02_mac_load_tx_status(struct mt76x02_dev *dev, struct mt76x02_tx_status *stat) @@ -491,7 +489,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, rcu_read_unlock(); } -int +static int mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate) { u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate); @@ -557,7 +555,6 @@ mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate) return 0; } -EXPORT_SYMBOL_GPL(mt76x02_mac_process_rate); void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr) { @@ -823,7 +820,6 @@ void mt76x02_mac_work(struct work_struct *work) ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, MT_CALIBRATE_INTERVAL); } -EXPORT_SYMBOL_GPL(mt76x02_mac_work); void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr) { @@ -832,7 +828,6 @@ void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr) mt76_rmw_field(dev, MT_MAC_APC_BSSID_H(idx), MT_MAC_APC_BSSID_H_ADDR, get_unaligned_le16(addr + 4)); } -EXPORT_SYMBOL_GPL(mt76x02_mac_set_bssid); static int mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) @@ -914,7 +909,6 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, bcn_idx - 1); return 0; } -EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon); void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, bool val) @@ -946,4 +940,3 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, else mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); } -EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon_enable); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index f65157600779..e2c47ca18d85 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -216,7 +216,6 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, struct mt76x02_tx_status *stat, u8 *update); int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, void *rxi); -int mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate); void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val); void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr); void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 9f083008dbd4..c0f923942edc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -606,7 +606,6 @@ const u16 mt76x02_beacon_offsets[16] = { 0xc000, 0xc000, }; -EXPORT_SYMBOL_GPL(mt76x02_beacon_offsets); static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev) { -- 2.17.0
[PATCH 4/4] mt76: add support for reporting tx status with skb
MT76x2/MT76x0 has somewhat unreliable tx status reporting, and for that reason the driver currently does not report per-skb tx ack status at all. This breaks things like client idle polling, which relies on the tx ack status of a transmitted nullfunc frame. This patch adds code to report skb-attached tx status if requested by mac80211 or the rate control module. Since tx status is polled from a simple FIFO register, the code needs to account for the possibility of tx status events getting lost. The code keeps a list of skbs for which tx status is required and passes them to mac80211 once tx status has been filled in and the DMA queue is done with it. If a tx status event is not received after one second, the status rates are cleared, and a succesful ACK is indicated to avoid spurious disassoc during assoc or client polling. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 1 + drivers/net/wireless/mediatek/mt76/mac80211.c | 3 + drivers/net/wireless/mediatek/mt76/mt76.h | 48 drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 - .../net/wireless/mediatek/mt76/mt76x02_mac.c | 71 +-- .../net/wireless/mediatek/mt76/mt76x02_mac.h | 19 --- .../net/wireless/mediatek/mt76/mt76x02_txrx.c | 25 ++-- .../wireless/mediatek/mt76/mt76x02_usb_core.c | 42 +++ .../net/wireless/mediatek/mt76/mt76x02_util.c | 1 + drivers/net/wireless/mediatek/mt76/tx.c | 111 ++ drivers/net/wireless/mediatek/mt76/usb.c | 1 + 11 files changed, 228 insertions(+), 95 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index f7fbd7016403..2d7bd26875c6 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -258,6 +258,7 @@ int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, return -ENOMEM; } + skb->prev = skb->next = NULL; dma_sync_single_for_cpu(dev->dev, t->dma_addr, sizeof(t->txwi), DMA_TO_DEVICE); ret = dev->drv->tx_prepare_skb(dev, &t->txwi, skb, q, wcid, sta, diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 2a699e8b79bf..85e05a825b5d 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -285,6 +285,7 @@ mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops) spin_lock_init(&dev->cc_lock); mutex_init(&dev->mutex); init_waitqueue_head(&dev->tx_wait); + skb_queue_head_init(&dev->status_list); return dev; } @@ -326,6 +327,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, ieee80211_hw_set(hw, TX_FRAG_LIST); ieee80211_hw_set(hw, MFP_CAPABLE); ieee80211_hw_set(hw, AP_LINK_PS); + ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); wiphy->flags |= WIPHY_FLAG_IBSS_RSN; @@ -357,6 +359,7 @@ void mt76_unregister_device(struct mt76_dev *dev) { struct ieee80211_hw *hw = dev->hw; + mt76_tx_status_flush(dev, NULL); ieee80211_unregister_hw(hw); mt76_tx_free(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 53ddc4fa5884..94ab00b549af 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -195,6 +195,8 @@ struct mt76_wcid { u8 tx_rate_nss; s8 max_txpwr_adj; bool sw_iv; + + u8 packet_id; }; struct mt76_txq { @@ -233,6 +235,22 @@ struct mt76_rx_tid { struct sk_buff *reorder_buf[]; }; +#define MT_TX_CB_DMA_DONE BIT(0) +#define MT_TX_CB_TXS_DONE BIT(1) +#define MT_TX_CB_TXS_FAILEDBIT(2) + +#define MT_PACKET_ID_MASK GENMASK(7, 0) +#define MT_PACKET_ID_NO_ACKMT_PACKET_ID_MASK + +#define MT_TX_STATUS_SKB_TIMEOUT HZ + +struct mt76_tx_cb { + unsigned long jiffies; + u8 wcid; + u8 pktid; + u8 flags; +}; + enum { MT76_STATE_INITIALIZED, MT76_STATE_RUNNING, @@ -400,6 +418,7 @@ struct mt76_dev { const struct mt76_queue_ops *queue_ops; wait_queue_head_t tx_wait; + struct sk_buff_head status_list; unsigned long wcid_mask[MT76_N_WCIDS / BITS_PER_LONG]; @@ -594,6 +613,13 @@ wcid_to_sta(struct mt76_wcid *wcid) return container_of(ptr, struct ieee80211_sta, drv_priv); } +static inline struct mt76_tx_cb *mt76_tx_skb_cb(struct sk_buff *skb) +{ + BUILD_BUG_ON(sizeof(struct mt76_tx_cb) > +sizeof(IEEE80211_SKB_CB(skb)->status.status_driver_data)); + return ((void *) IEEE80211_SKB_CB(skb)->status.status_driver_data); +} + int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid,
[PATCH 2/4] mt76: mt76x02: skip station tx status for non-sta wcid entries
Fixes a crash that could occur if a frame is sent to a station, but the station's wcid was not used (e.g. for software encrypted mgmt tx) Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 34fc9f2eb51f..ad8df680c6a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -450,7 +450,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid)) wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]); - if (wcid) { + if (wcid && wcid->sta) { void *priv; priv = msta = container_of(wcid, struct mt76x02_sta, wcid); -- 2.17.0
[PATCH 3/4] mt76: mt76x02: only override control->sta on sw-encrypted tx
control->sta is set to NULL early when encryption is turned on for the station and info->control.hw_key is not set. This code is missing a check for the 802.11 header protected flag, otherwise it resets the station for other frames, e.g. client probing frames. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 7ec3f8f5f228..c008e08602f3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -22,6 +22,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct mt76x02_dev *dev = hw->priv; struct ieee80211_vif *vif = info->control.vif; @@ -33,7 +34,8 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, msta = (struct mt76x02_sta *)control->sta->drv_priv; wcid = &msta->wcid; /* sw encrypted frames */ - if (!info->control.hw_key && wcid->hw_key_idx != 0xff) + if (!info->control.hw_key && wcid->hw_key_idx != 0xff && + ieee80211_has_protected(hdr->frame_control)) control->sta = NULL; } -- 2.17.0
[PATCH] mt76x0: use band parameter for LC calibration
We use always 1 as band parameter for MCU_CAL_LC, this break 2GHz, we should use 0 for this band instead. Patch fixes problems happened sometimes when try to associate with 2GHz AP and manifest by errors like below: [14680.920823] wlan0: authenticate with 18:31:bf:c0:51:b0 [14681.109506] wlan0: send auth to 18:31:bf:c0:51:b0 (try 1/3) [14681.310454] wlan0: send auth to 18:31:bf:c0:51:b0 (try 2/3) [14681.518469] wlan0: send auth to 18:31:bf:c0:51:b0 (try 3/3) [14681.726499] wlan0: authentication with 18:31:bf:c0:51:b0 timed out Fixes: 9aec146d0f6b ("mt76x0: pci: introduce mt76x0_phy_calirate routine") Signed-off-by: Stanislaw Gruszka --- This is for 4.20. drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index c734987a344c..ca24b5716b58 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -522,6 +522,7 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; + int is_5ghz = (chan->band == NL80211_BAND_5GHZ) ? 1 : 0; u32 val, tx_alc, reg_val; if (is_mt7630(dev)) @@ -542,7 +543,7 @@ void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on) reg_val = mt76_rr(dev, MT_BBP(IBI, 9)); mt76_wr(dev, MT_BBP(IBI, 9), 0xff7e); - if (chan->band == NL80211_BAND_5GHZ) { + if (is_5ghz) { if (chan->hw_value < 100) val = 0x701; else if (chan->hw_value < 140) @@ -555,7 +556,7 @@ void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on) mt76x02_mcu_calibrate(dev, MCU_CAL_FULL, val, false); msleep(350); - mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 1, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_LC, is_5ghz, false); usleep_range(15000, 2); mt76_wr(dev, MT_BBP(IBI, 9), reg_val); -- 2.7.5
[PATCH v3 5/5] nfc: pn532_uart: Make use of pn532 autopoll
This switches the pn532 UART phy driver from manually polling to the new autopoll mechanism. Signed-off-by: Lars Poeschel --- drivers/nfc/pn533/uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c index 8fd71c8953ca..a95ca01745ca 100644 --- a/drivers/nfc/pn533/uart.c +++ b/drivers/nfc/pn533/uart.c @@ -207,7 +207,7 @@ static int pn532_uart_probe(struct serdev_device *serdev) goto err_free; pn532->serdev = serdev; - priv = pn533_register_device(PN533_DEVICE_PN532, + priv = pn533_register_device(PN533_DEVICE_PN532_AUTOPOLL, PN533_NO_TYPE_B_PROTOCOLS, PN533_PROTO_REQ_ACK_RESP, pn532, &uart_phy_ops, NULL, -- 2.19.1
[PATCH v3 4/5] nfc: pn533: Add autopoll capability
pn532 devices support an autopoll command, that lets the chip automatically poll for selected nfc technologies instead of manually looping through every single nfc technology the user is interested in. This is faster and less cpu and bus intensive than manually polling. This adds this autopoll capability to the pn533 driver. Signed-off-by: Lars Poeschel --- drivers/nfc/pn533/pn533.c | 193 +- drivers/nfc/pn533/pn533.h | 10 +- 2 files changed, 197 insertions(+), 6 deletions(-) diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c index a0cc1cc45292..c80ee79af86e 100644 --- a/drivers/nfc/pn533/pn533.c +++ b/drivers/nfc/pn533/pn533.c @@ -197,6 +197,32 @@ struct pn533_cmd_jump_dep_response { u8 gt[]; } __packed; +struct pn532_autopoll_resp { + u8 type; + u8 ln; + u8 tg; + u8 tgdata[]; +} __packed; + +/* PN532_CMD_IN_AUTOPOLL */ +#define PN532_AUTOPOLL_POLLNR_INFINITE 0xff +#define PN532_AUTOPOLL_PERIOD 0x03 /* in units of 150 ms */ + +#define PN532_AUTOPOLL_TYPE_GENERIC_1060x00 +#define PN532_AUTOPOLL_TYPE_GENERIC_2120x01 +#define PN532_AUTOPOLL_TYPE_GENERIC_4240x02 +#define PN532_AUTOPOLL_TYPE_JEWEL 0x04 +#define PN532_AUTOPOLL_TYPE_MIFARE 0x10 +#define PN532_AUTOPOLL_TYPE_FELICA212 0x11 +#define PN532_AUTOPOLL_TYPE_FELICA424 0x12 +#define PN532_AUTOPOLL_TYPE_ISOA 0x20 +#define PN532_AUTOPOLL_TYPE_ISOB 0x23 +#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_1060x40 +#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_2120x41 +#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_4240x42 +#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106 0x80 +#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_212 0x81 +#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_424 0x82 /* PN533_TG_INIT_AS_TARGET */ #define PN533_INIT_TARGET_PASSIVE 0x1 @@ -1401,6 +1427,101 @@ static int pn533_poll_dep(struct nfc_dev *nfc_dev) return rc; } +static int pn533_autopoll_complete(struct pn533 *dev, void *arg, + struct sk_buff *resp) +{ + u8 nbtg; + int rc; + struct pn532_autopoll_resp *apr; + struct nfc_target nfc_tgt; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + + nfc_err(dev->dev, "%s autopoll complete error %d\n", + __func__, rc); + + if (rc == -ENOENT) { + if (dev->poll_mod_count != 0) + return rc; + goto stop_poll; + } else if (rc < 0) { + nfc_err(dev->dev, + "Error %d when running autopoll\n", rc); + goto stop_poll; + } + } + + nbtg = resp->data[0]; + if ((nbtg > 2) || (nbtg <= 0)) + return -EAGAIN; + + apr = (struct pn532_autopoll_resp *)&resp->data[1]; + while (nbtg--) { + memset(&nfc_tgt, 0, sizeof(struct nfc_target)); + switch (apr->type) { + case PN532_AUTOPOLL_TYPE_ISOA: + dev_dbg(dev->dev, "ISOA"); + rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_FELICA212: + case PN532_AUTOPOLL_TYPE_FELICA424: + dev_dbg(dev->dev, "FELICA"); + rc = pn533_target_found_felica(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_JEWEL: + dev_dbg(dev->dev, "JEWEL"); + rc = pn533_target_found_jewel(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_ISOB: + dev_dbg(dev->dev, "ISOB"); + rc = pn533_target_found_type_b(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_MIFARE: + dev_dbg(dev->dev, "Mifare"); + rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + default: + nfc_err(dev->dev, + "Unknown current poll modulation"); + rc = -EPROTO; + } + + if (rc) + goto done; + + if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { + nfc_err(dev->dev, + "The Tg found do
[PATCH v3 3/5] nfc: pn533: add UART phy driver
This adds the UART phy interface for the pn533 driver. The pn533 driver can be used through UART interface this way. It is implemented as a serdev device. Signed-off-by: Lars Poeschel --- Changes in v3: - depend on SERIAL_DEV_BUS in Kconfig Changes in v2: - switched from tty line discipline to serdev, resulting in many simplifications - SPDX License Identifier drivers/nfc/pn533/Kconfig | 11 ++ drivers/nfc/pn533/Makefile | 2 + drivers/nfc/pn533/pn533.h | 8 ++ drivers/nfc/pn533/uart.c | 283 + 4 files changed, 304 insertions(+) create mode 100644 drivers/nfc/pn533/uart.c diff --git a/drivers/nfc/pn533/Kconfig b/drivers/nfc/pn533/Kconfig index d94122dd30e4..29df7d97d209 100644 --- a/drivers/nfc/pn533/Kconfig +++ b/drivers/nfc/pn533/Kconfig @@ -25,3 +25,14 @@ config NFC_PN533_I2C If you choose to build a module, it'll be called pn533_i2c. Say N if unsure. + +config NFC_PN532_UART + tristate "NFC PN532 device support (UART)" + depends on SERIAL_DEV_BUS + select NFC_PN533 + ---help--- + This module adds support for the NXP pn532 UART interface. + Select this if your platform is using the UART bus. + + If you choose to build a module, it'll be called pn532_uart. + Say N if unsure. diff --git a/drivers/nfc/pn533/Makefile b/drivers/nfc/pn533/Makefile index 51d24c622fcb..bdfd6860d5e4 100644 --- a/drivers/nfc/pn533/Makefile +++ b/drivers/nfc/pn533/Makefile @@ -3,7 +3,9 @@ # pn533_usb-objs = usb.o pn533_i2c-objs = i2c.o +pn532_uart-objs = uart.o obj-$(CONFIG_NFC_PN533) += pn533.o obj-$(CONFIG_NFC_PN533_USB) += pn533_usb.o obj-$(CONFIG_NFC_PN533_I2C) += pn533_i2c.o +obj-$(CONFIG_NFC_PN532_UART) += pn532_uart.o diff --git a/drivers/nfc/pn533/pn533.h b/drivers/nfc/pn533/pn533.h index 88d569666c51..ca00508eefff 100644 --- a/drivers/nfc/pn533/pn533.h +++ b/drivers/nfc/pn533/pn533.h @@ -55,6 +55,11 @@ /* Preamble (1), SoPC (2), ACK Code (2), Postamble (1) */ #define PN533_STD_FRAME_ACK_SIZE 6 +/* + * Preamble (1), SoPC (2), Packet Length (1), Packet Length Checksum (1), + * Specific Application Level Error Code (1) , Postamble (1) + */ +#define PN533_STD_ERROR_FRAME_SIZE 8 #define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen]) #define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1]) /* Half start code (3), LEN (4) should be 0x for extended frame */ @@ -96,6 +101,9 @@ #define PN533_CMD_MI_MASK 0x40 #define PN533_CMD_RET_SUCCESS 0x00 +#define PN533_FRAME_DATALEN_ACK 0x00 +#define PN533_FRAME_DATALEN_ERROR 0x01 +#define PN533_FRAME_DATALEN_EXTENDED 0xFF enum pn533_protocol_type { PN533_PROTO_REQ_ACK_RESP = 0, diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c new file mode 100644 index ..8fd71c8953ca --- /dev/null +++ b/drivers/nfc/pn533/uart.c @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for NXP PN532 NFC Chip - UART transport layer + * + * Copyright (C) 2018 Lemonage Software GmbH + * Author: Lars Pöschel + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "pn533.h" + +#define VERSION "0.1" +#define PN532_UART_DRIVER_NAME "pn532_uart" + +#define PN532_UART_SKB_BUFF_LEN(PN533_CMD_DATAEXCH_DATA_MAXLEN * 2) + +struct pn532_uart_phy { + struct serdev_device *serdev; + struct sk_buff *recv_skb; + struct pn533 *priv; + int send_wakeup; + struct timer_list cmd_timeout; + struct sk_buff *cur_out_buf; +}; + +static int pn532_uart_send_frame(struct pn533 *dev, + struct sk_buff *out) +{ + static const u8 wakeup[] = { + 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + /* wakeup sequence and dummy bytes for waiting time */ + struct pn532_uart_phy *pn532 = dev->phy; + int count; + + print_hex_dump_debug("PN532_uart TX: ", DUMP_PREFIX_NONE, 16, 1, +out->data, out->len, false); + + pn532->cur_out_buf = out; + if (pn532->send_wakeup) + count = serdev_device_write(pn532->serdev, + wakeup, sizeof(wakeup), + MAX_SCHEDULE_TIMEOUT); + + count = serdev_device_write(pn532->serdev, out->data, out->len, + MAX_SCHEDULE_TIMEOUT); + if (PN533_FRAME_CMD(((struct pn533_std_frame *)out->data)) == + PN533_CMD_SAM_CONFIGURATION) + pn532->send_wakeup = 0; + + mod_timer(&pn532->cmd_timeout, HZ / 40 + jiffies); + return 0; +} + +static int pn532_uart_send_ack(struct pn533 *dev, gfp_t flags) +{ + struct pn532_uart_phy *pn532 = dev->phy; + static const u8 ack[PN533_STD_FRAME_ACK_SIZE] = { + 0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; + /* spec 7.1.1.3: Pream
[PATCH v3 1/5] nfc: pn533: i2c: "pn532" as dt compatible string
It is favourable to have one unified compatible string for devices that have multiple interfaces. So this adds simply "pn532" as the devicetree binding compatible string and makes a note that the old ones are deprecated. Signed-off-by: Lars Poeschel --- drivers/nfc/pn533/i2c.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/nfc/pn533/i2c.c b/drivers/nfc/pn533/i2c.c index 4389eb4c8d0b..f4eae9dd5305 100644 --- a/drivers/nfc/pn533/i2c.c +++ b/drivers/nfc/pn533/i2c.c @@ -258,6 +258,11 @@ static int pn533_i2c_remove(struct i2c_client *client) } static const struct of_device_id of_pn533_i2c_match[] = { + { .compatible = "nxp,pn532", }, + /* +* NOTE: The use of the compatibles with the trailing "...-i2c" is +* deprecated and will be removed. +*/ { .compatible = "nxp,pn533-i2c", }, { .compatible = "nxp,pn532-i2c", }, {}, -- 2.19.1
Re: [PATCH v2 1/4] nfc: pn533: add UART phy driver
On Sat, Oct 20, 2018 at 11:27:33AM +0200, Johan Hovold wrote: > On Fri, Oct 19, 2018 at 10:57:28AM +0200, Lars Poeschel wrote: > > On Thu, Oct 18, 2018 at 05:00:28PM +0200, Marcel Holtmann wrote: > > > > > --- a/drivers/nfc/pn533/Kconfig > > > > +++ b/drivers/nfc/pn533/Kconfig > > > > @@ -25,3 +25,13 @@ config NFC_PN533_I2C > > > > > > > > If you choose to build a module, it'll be called pn533_i2c. > > > > Say N if unsure. > > > > + > > > > +config NFC_PN532_UART > > > > + tristate "NFC PN532 device support (UART)” > > > > > > you are missing the "depends on SERIAL_DEV_BUS” here. > > > > Yes, absolutely right. I missed that. I will post a follow-up. > > > > BTW a question: > > Only enabling SERIAL_DEV_BUS did not suffice for me. I also had to > > enable SERIAL_DEV_CTRL_TTYPORT, otherwise the probe of the driver was > > not called. This seems a bit odd to me. This option seems unrelated, but > > without it, it did not work. > > > > Should I better depend on SERIAL_DEV_CTRL_TTYPORT then ? > > No, SERIAL_DEV_BUS is the correct (build-time) dependency. > > In principle, your driver will work with any serdev-controller > implementation even if we currently only have one of those in the kernel > (and SERIAL_DEV_CTRL_TTYPORT therefore default to Y whenever > SERIAL_DEV_BUS is selected). Thanks, this makes sense for me now. I will post a follow-up patchset shortly. Regards, Lars
Re: [PATCH] mac80211: support FTM responder configuration/statistics
Hi Pradeep, On Wed, 2018-10-03 at 20:19 -0700, Pradeep Kumar Chitrapu wrote: > New bss param ftm_responder is used to notify the driver to > enable fine timing request (FTM) responder role in AP mode. I just realized that this is broken in nl80211_channel_switch() and ieee80211_set_csa_beacon(), doing a CSA will always disable FTM unless it was actually included in the new configuration. Doing the trivial thing: memset(¶ms, 0, sizeof(params)); + params.beacon_after.ftm_responder = -1; in nl80211_channel_switch() will not help because then mac80211 will lose all the extra configuration, and will actually store -1 into its enabled value which is really strange. I'd appreciate if you could take a look at this. Thanks, johannes