From patchwork Wed Jan 23 10:19:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Porsch X-Patchwork-Id: 2023671 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 1CE9F3FDD1 for ; Wed, 23 Jan 2013 10:19:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754571Ab3AWKTh (ORCPT ); Wed, 23 Jan 2013 05:19:37 -0500 Received: from mail-bk0-f48.google.com ([209.85.214.48]:59161 "EHLO mail-bk0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754210Ab3AWKTe (ORCPT ); Wed, 23 Jan 2013 05:19:34 -0500 Received: by mail-bk0-f48.google.com with SMTP id jk14so1711255bkc.21 for ; Wed, 23 Jan 2013 02:19:33 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:x-gm-message-state; bh=BelGmK+ggmrKh3K8iMcSsEOcHrdvvDQCS65MlI10asE=; b=Hcm8rFlZmuXN7F4DIUBCufHUk63qcxQtH6Gs1t6+6JQ1nik3hSDZwf9EHEGTcXp88i CSn9XVPAnzbu9zQnBl3vBXoVmZJnsrhUtYaj1Kj3PdYocNulp/i0tU2X4GBpNdDLr7pH j88K5xovWERM/nq7Uxul8GXB6qoT3uv0Q1TOQRPuF9JgcBSdlXDehR9jZNocjVoFsYhR 33VQkglLvWEhk9iy5oRlHK1qKAsaoRPAejg6SKxEv4hlxWeHU/Osgx6QUX5CmpsNmrK0 mY27Mw5hT5G3AN12lSb8BSAGW18SQrjPMVKh7CF3h6dLNeYShN+Q+g2nvVIw5g6dubxV Usrg== X-Received: by 10.204.149.86 with SMTP id s22mr223319bkv.57.1358936372841; Wed, 23 Jan 2013 02:19:32 -0800 (PST) Received: from X220-marco.infotech.tu-chemnitz.de (perseus.infotech.tu-chemnitz.de. [134.109.4.8]) by mx.google.com with ESMTPS id f24sm13524703bkv.7.2013.01.23.02.19.31 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 23 Jan 2013 02:19:32 -0800 (PST) From: Marco Porsch To: mcgrof@qca.qualcomm.com, jouni@qca.qualcomm.com, vthiagar@qca.qualcomm.com, senthilb@qca.qualcomm.com, johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, devel@lists.open80211s.org, ath9k-devel@lists.ath9k.org, Marco Porsch Subject: [RFC 3/3] ath9k: mesh powersave support Date: Wed, 23 Jan 2013 11:19:20 +0100 Message-Id: <1358936360-7795-4-git-send-email-marco@cozybit.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1358936360-7795-1-git-send-email-marco@cozybit.com> References: <1358936360-7795-1-git-send-email-marco@cozybit.com> X-Gm-Message-State: ALoCoQl+YkVfkrerGk0WpT2lyLS+PZXWWC0HVr70r1usIwUbWQJTdElsdExX37QTCTQHVE2cUF0q Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Register mesh PS ops on interface add and de-register on removal. When enabling mesh PS, do not enable the hardware's TIM timer interrupt. React to mac80211 doze/wakeup calls. Add a PS status flag PS_MAC80211_CTL to store last mesh PS command from mac80211. Signed-off-by: Marco Porsch --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 46 +++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 8250330..f11c210 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -651,6 +651,7 @@ enum sc_op_flags { #define PS_WAIT_FOR_TX_ACK BIT(3) #define PS_BEACON_SYNC BIT(4) #define PS_WAIT_FOR_ANI BIT(5) +#define PS_MAC80211_CTL BIT(6) struct ath_rate_table; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 0fb53d6..2929808 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -132,7 +132,8 @@ void ath9k_ps_restore(struct ath_softc *sc) PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | PS_WAIT_FOR_TX_ACK | - PS_WAIT_FOR_ANI))) { + PS_WAIT_FOR_ANI | + PS_MAC80211_CTL))) { mode = ATH9K_PM_NETWORK_SLEEP; if (ath9k_hw_btcoex_is_enabled(sc->sc_ah)) ath9k_btcoex_stop_gen_timer(sc); @@ -824,6 +825,38 @@ static void ath9k_stop(struct ieee80211_hw *hw) ath_dbg(common, CONFIG, "Driver halt\n"); } +static void ath9k_mesh_doze(struct ieee80211_hw *hw) +{ + struct ath_softc *sc = hw->priv; + unsigned long flags; + + ath9k_ps_wakeup(sc); + spin_lock_irqsave(&sc->sc_pm_lock, flags); + /* in mesh mode mac80211 checks beacons and CAB */ + sc->ps_flags &= ~(PS_WAIT_FOR_BEACON | + PS_WAIT_FOR_CAB | + PS_MAC80211_CTL); + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); + ath9k_ps_restore(sc); +} + +static void ath9k_mesh_wakeup(struct ieee80211_hw *hw) +{ + struct ath_softc *sc = hw->priv; + unsigned long flags; + + ath9k_ps_wakeup(sc); + spin_lock_irqsave(&sc->sc_pm_lock, flags); + sc->ps_flags |= PS_MAC80211_CTL; + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); + ath9k_ps_restore(sc); +} + +static const struct ieee80211_mps_ops ath9k_mesh_ps_ops = { + .hw_doze = ath9k_mesh_doze, + .hw_wakeup = ath9k_mesh_wakeup, +}; + bool ath9k_uses_beacons(int type) { switch (type) { @@ -934,6 +967,11 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, ah->opmode = NL80211_IFTYPE_ADHOC; else ah->opmode = NL80211_IFTYPE_STATION; + + if (ah->opmode == NL80211_IFTYPE_MESH_POINT) + ieee80211_mps_init(hw, &ath9k_mesh_ps_ops); + else if (old_opmode == NL80211_IFTYPE_MESH_POINT) + ieee80211_mps_init(hw, NULL); } ath9k_hw_setopmode(ah); @@ -1037,7 +1075,9 @@ static void ath9k_enable_ps(struct ath_softc *sc) struct ath_common *common = ath9k_hw_common(ah); sc->ps_enabled = true; - if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP) && + sc->sc_ah->opmode != NL80211_IFTYPE_MESH_POINT) { + /* in mesh mode we trigger wakeups from mac80211 */ if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) { ah->imask |= ATH9K_INT_TIM_TIMER; ath9k_hw_set_interrupts(ah); @@ -1178,7 +1218,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) * We just prepare to enable PS. We have to wait until our AP has * ACK'd our null data frame to disable RX otherwise we'll ignore * those ACKs and end up retransmitting the same null data frames. - * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode. + * IEEE80211_CONF_CHANGE_PS is passed by mac80211 for STA or mesh mode. */ if (changed & IEEE80211_CONF_CHANGE_PS) { unsigned long flags;