From d2a993e20e717a4ccbfa9a58b29362e4446208a0 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 7 Oct 2014 10:14:36 +0530 Subject: ath: Fix smatch warning drivers/net/wireless/ath/main.c:88 ath_printk() error: we previously assumed 'common->hw' could be null (see line 82) Reported-by: Dan Carpenter Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/ath') diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c index 83f47af19280..338d72337604 100644 --- a/drivers/net/wireless/ath/main.c +++ b/drivers/net/wireless/ath/main.c @@ -79,13 +79,13 @@ void ath_printk(const char *level, const struct ath_common* common, vaf.fmt = fmt; vaf.va = &args; - if (common && common->hw && common->hw->wiphy) + if (common && common->hw && common->hw->wiphy) { printk("%sath: %s: %pV", level, wiphy_name(common->hw->wiphy), &vaf); - else + trace_ath_log(common->hw->wiphy, &vaf); + } else { printk("%sath: %pV", level, &vaf); - - trace_ath_log(common->hw->wiphy, &vaf); + } va_end(args); } -- cgit v1.2.3 From b18111d911980af52bead74ee45250cc96ad5108 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 7 Oct 2014 10:14:37 +0530 Subject: ath9k: Fix crash in MCC mode When a channel context is removed, the hw_queue_base is set to -1, this will result in a panic because ath9k_chanctx_stop_queues() can be called on an interface that is not assigned to any context yet - for example, when trying to scan. Fix this issue by setting the hw_queue_base to zero when a channel context is removed. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 205162449b72..6f6a974f7fdb 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2332,7 +2332,7 @@ static void ath9k_remove_chanctx(struct ieee80211_hw *hw, conf->def.chan->center_freq); ctx->assigned = false; - ctx->hw_queue_base = -1; + ctx->hw_queue_base = 0; ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_UNASSIGN); mutex_unlock(&sc->mutex); -- cgit v1.2.3 From c393d179924685d5c8c72446c5b6401f25fdb2a0 Mon Sep 17 00:00:00 2001 From: Marek Puzyniak Date: Tue, 7 Oct 2014 17:04:30 +0200 Subject: ath9k_htc: avoid kernel panic in ath9k_hw_reset hw pointer of ath_hw is not assigned to proper value in function ath9k_hw_reset what finally causes kernel panic. This can be solved by proper initialization of ath_hw in ath9k_init_priv. Signed-off-by: Marek Puzyniak Acked-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless/ath') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index d779f4fa50e3..4014c4be6e79 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -464,6 +464,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, return -ENOMEM; ah->dev = priv->dev; + ah->hw = priv->hw; ah->hw_version.devid = devid; ah->hw_version.usbdev = drv_info; ah->ah_flags |= AH_USE_EEPROM; -- cgit v1.2.3 From ca14405e3b25b38221d027d8970c1d74ed0b6532 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 8 Oct 2014 08:43:19 +0530 Subject: ath9k: Fix sequence number assignment Currently, ath9k uses a global counter for all frames that need to be assigned a sequence number. QoS-data frames are handled properly since they have a per-tid counter. But, beacons and other management frames use the same counter even if multiple interfaces or contexts are present. Fix this issue by making the counter per-interface and using it when mac80211 sets IEEE80211_TX_CTL_ASSIGN_SEQ. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 4 +++- drivers/net/wireless/ath/ath9k/beacon.c | 12 ++---------- drivers/net/wireless/ath/ath9k/tx99.c | 8 +++++++- drivers/net/wireless/ath/ath9k/xmit.c | 34 ++++++++++++++++++++++----------- 4 files changed, 35 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless/ath') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bfa0b1518da1..01a7db061c6a 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -294,7 +294,6 @@ struct ath_tx_control { * (axq_qnum). */ struct ath_tx { - u16 seq_no; u32 txqsetup; spinlock_t txbuflock; struct list_head txbuf; @@ -563,6 +562,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs); int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_tx_queue_info *q); void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); +void ath_assign_seq(struct ath_common *common, struct sk_buff *skb); int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl); void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -592,6 +592,8 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, struct ath_vif { struct list_head list; + u16 seq_no; + /* BSS info */ u8 bssid[ETH_ALEN]; u16 aid; diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index a6af855ef6ed..ecb783beeec2 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -144,16 +144,8 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust; info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - /* - * TODO: make sure the seq# gets assigned properly (vs. other - * TX frames) - */ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } + + ath_assign_seq(common, skb); if (vif->p2p) ath9k_beacon_add_noa(sc, avp, skb); diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 8a69d08ec55c..40ab65e6882f 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -54,6 +54,12 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) struct ieee80211_hdr *hdr; struct ieee80211_tx_info *tx_info; struct sk_buff *skb; + struct ath_vif *avp; + + if (!sc->tx99_vif) + return NULL; + + avp = (struct ath_vif *)sc->tx99_vif->drv_priv; skb = alloc_skb(len, GFP_KERNEL); if (!skb) @@ -71,7 +77,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); + hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); tx_info = IEEE80211_SKB_CB(skb); memset(tx_info, 0, sizeof(*tx_info)); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 151ae49fa57e..493a183d0aaf 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2139,6 +2139,28 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, return bf; } +void ath_assign_seq(struct ath_common *common, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct ath_vif *avp; + + if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) + return; + + if (!vif) + return; + + avp = (struct ath_vif *)vif->drv_priv; + + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + avp->seq_no += 0x10; + + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); +} + static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl) { @@ -2162,17 +2184,7 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, if (info->control.hw_key) frmlen += info->control.hw_key->icv_len; - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } + ath_assign_seq(ath9k_hw_common(sc->sc_ah), skb); if ((vif && vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_AP_VLAN) || -- cgit v1.2.3