From patchwork Mon Jul 8 13:14:10 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Wunderlich X-Patchwork-Id: 2824846 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 17FEF9F756 for ; Mon, 8 Jul 2013 13:14:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B37F02017C for ; Mon, 8 Jul 2013 13:14:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4321A20181 for ; Mon, 8 Jul 2013 13:14:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751981Ab3GHNOd (ORCPT ); Mon, 8 Jul 2013 09:14:33 -0400 Received: from cora.hrz.tu-chemnitz.de ([134.109.228.40]:47996 "EHLO cora.hrz.tu-chemnitz.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751213Ab3GHNO2 (ORCPT ); Mon, 8 Jul 2013 09:14:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tu-chemnitz.de; s=dkim2010; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=tWpO9pmNYW1VqC7FwSYG96Xq74ATc2pM6PALLsGnBRY=; b=UmhOHJ3U4KCyqAjrmWVIgfQAPR3C60V+3HGzw/PNtaZ9+tPPzKjr0DZA67XnPwQdSAMe0AQcR6ssvKTg9jH+xitBT9pzX9kQpnOi9DwKupJkyO3ujqNcWmOOJKeXC9YMCymGOVNt7VT4W0DUJd2K9b9x3IdSkWcS5bRuS2192MU=; Received: from p4ffe4810.dip0.t-ipconnect.de ([79.254.72.16] helo=pandem0nium) by cora.hrz.tu-chemnitz.de with esmtpsa (TLSv1:DHE-RSA-AES128-SHA:128) (Exim 4.80.1) (envelope-from ) id 1UwBGt-0004sW-6G; Mon, 08 Jul 2013 15:14:27 +0200 Received: from dotslash by pandem0nium with local (Exim 4.80) (envelope-from ) id 1UwBGs-0003Cc-0A; Mon, 08 Jul 2013 15:14:26 +0200 From: Simon Wunderlich To: Johannes Berg Cc: linux-wireless@vger.kernel.org, Mathias Kretschmer , Simon Wunderlich Subject: [PATCHv3 5/5] ath9k: enable CSA functionality in ath9k Date: Mon, 8 Jul 2013 15:14:10 +0200 Message-Id: <1373289250-12259-6-git-send-email-siwu@hrz.tu-chemnitz.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1373289250-12259-1-git-send-email-siwu@hrz.tu-chemnitz.de> References: <1373289250-12259-1-git-send-email-siwu@hrz.tu-chemnitz.de> X-purgate: clean X-purgate-type: clean X-purgate-ID: 154106::1373289267-0000051A-B54CC71B/0-0/0-0 X-Scan-AV: cora.hrz.tu-chemnitz.de; 2013-07-08 15:14:27; d41c1cbd0878c80ea988f426d6ce1c08 X-Scan-SA: cora.hrz.tu-chemnitz.de; 2013-07-08 15:14:27; 3886a7e5ca43ad376cd13acd28a2468d X-Spam-Score: -1.0 (-) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP CSA is only enabled for one interface, but the same limitation applies for mac80211 too. It checks whether the beacon has been sent (different approaches for non-EDMA-enabled and EDMA-enabled devices), and completes the channel switch after that. Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer --- Changes to PATCHv2: * announce support for channel switch Changes to PATCHv1: * complete channel switch after the last beacon has been sent --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 ++ drivers/net/wireless/ath/ath9k/beacon.c | 21 +++++++++++++++++++++ drivers/net/wireless/ath/ath9k/init.c | 1 + drivers/net/wireless/ath/ath9k/main.c | 17 +++++++++++++++++ drivers/net/wireless/ath/ath9k/xmit.c | 2 ++ 5 files changed, 43 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 579ed9c..3745487 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -424,6 +424,7 @@ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif); void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif); void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif); void ath9k_set_beacon(struct ath_softc *sc); +bool ath9k_csa_is_finished(struct ath_softc *sc); /*******************/ /* Link Monitoring */ @@ -751,6 +752,7 @@ struct ath_softc { #endif struct ath_descdma txsdma; + struct ieee80211_vif *csa_vif; struct ath_ant_comb ant_comb; u8 ant_tx, ant_rx; diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index fd1eeba..e400151 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -310,6 +310,23 @@ void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif) (unsigned long long)tsfadjust, avp->av_bslot); } +bool ath9k_csa_is_finished(struct ath_softc *sc) +{ + struct ieee80211_vif *vif; + + vif = sc->csa_vif; + if (!vif || !vif->csa_active) + return false; + + if (!ieee80211_csa_is_complete(vif)) + return false; + + ieee80211_csa_finish(vif); + vif->csa_active = 0; + sc->csa_vif = NULL; + return true; +} + void ath9k_beacon_tasklet(unsigned long data) { struct ath_softc *sc = (struct ath_softc *)data; @@ -355,6 +372,10 @@ void ath9k_beacon_tasklet(unsigned long data) return; } + /* EDMA devices check that in the tx completion function. */ + if (!edma && ath9k_csa_is_finished(sc)) + return; + slot = ath9k_beacon_choose_slot(sc); vif = sc->beacon.bslot[slot]; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index f359b0d..3ce83c4 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -807,6 +807,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; #ifdef CONFIG_PM_SLEEP if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d1ce3da..6844968 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1026,6 +1026,9 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, if (ath9k_uses_beacons(vif->type)) ath9k_beacon_remove_slot(sc, vif); + if (sc->csa_vif == vif) + sc->csa_vif = NULL; + ath9k_ps_wakeup(sc); ath9k_calculate_summary_state(hw, NULL); ath9k_ps_restore(sc); @@ -2319,6 +2322,19 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) clear_bit(SC_OP_SCANNING, &sc->sc_flags); } +static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_chan_def *chandef) +{ + struct ath_softc *sc = hw->priv; + + /* mac80211 does not support CSA in multi-if cases (yet) */ + if (WARN_ON(sc->csa_vif)) + return; + + sc->csa_vif = vif; +} + struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -2366,4 +2382,5 @@ struct ieee80211_ops ath9k_ops = { #endif .sw_scan_start = ath9k_sw_scan_start, .sw_scan_complete = ath9k_sw_scan_complete, + .channel_switch_beacon = ath9k_channel_switch_beacon, }; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index eab0fcb..cec670d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2282,6 +2282,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) if (ts.qid == sc->beacon.beaconq) { sc->beacon.tx_processed = true; sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); + + ath9k_csa_is_finished(sc); continue; }