From patchwork Mon Mar 9 13:36:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 5967501 Return-Path: X-Original-To: patchwork-ath10k@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 301E1BF440 for ; Mon, 9 Mar 2015 13:39:45 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7F09220263 for ; Mon, 9 Mar 2015 13:39:41 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3EBE920259 for ; Mon, 9 Mar 2015 13:39:40 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YUxu6-0000tb-70; Mon, 09 Mar 2015 13:39:30 +0000 Received: from mail-la0-x234.google.com ([2a00:1450:4010:c03::234]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YUxu1-0000rZ-UE for ath10k@lists.infradead.org; Mon, 09 Mar 2015 13:39:28 +0000 Received: by labgd6 with SMTP id gd6so23880127lab.6 for ; Mon, 09 Mar 2015 06:39:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tieto.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MRhaaJ3m7nSk4cbQLpkezkuEaeeqCFH6ZTuXbN329tg=; b=zdgNKyguAnTD1WAacpgnB18ndSKeuVD2TM+0vpjVj5syDncrNbdseDCo2T2HLsSPCN SSJEk/1uvVbKJR/n2EX1MJ2aqeLlkzKqpq7Bmwuy+9MvMwbNfPepCn8f84biQSkvueo6 9e3A1aOsuvkEyFrqPlLDmz0ZK4o3gmIVR7Ugc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=MRhaaJ3m7nSk4cbQLpkezkuEaeeqCFH6ZTuXbN329tg=; b=AqJ51o4yeoGFcWTdHm4G1dxEUrbuTigq4oDNofh1P5f7pW71xys3IYpI8RaiOSx1wI tI5xLS5cyMQ6mCn7lkyk6BQliIojRM3pGZO6ORUxlq1JKtbtWfsTu7c/WoaZP0Y+eDys I2l4n4sounsUSoApsIIWbhOQVIvSG6JyYyZazlxkXXslpdHT1K2U+44MInzgr/iFyknH gWR3Oc3RkHxMQipwoZ/K6nXX9EdR4n98IenFZCVvbJkCIh6b1Tc60lCf2gZdn9Ffg/h2 yAZi5yvCN9iTmcoIW3jWRGCQfDYSePgSZ1cBKaTn6/Cv1GV8dBYQODdv77JzmO13moHm 2FQQ== X-Gm-Message-State: ALoCoQlsMo8YAbXat6V3j+UAw8NF3MDgNEj5dG/FW7d1AExnrLUDNG0/j1kATKHlfXUa++65f4q9dxjmqxTZPy0jM8cO9lE6f4Xp1WzmkvO38mrV2SjrIxnFY5j4cQJvw7vO6bY6s0qNvO7uyoG5yHIJ/6rizMrVCc3dXKGUnVqOJ6EC/QUa/5o= X-Received: by 10.112.169.39 with SMTP id ab7mr25118016lbc.85.1425908343360; Mon, 09 Mar 2015 06:39:03 -0700 (PDT) Received: from localhost.localdomain ([91.198.246.8]) by mx.google.com with ESMTPSA id p11sm432044lbs.13.2015.03.09.06.39.01 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 09 Mar 2015 06:39:01 -0700 (PDT) From: Michal Kazior To: ath10k@lists.infradead.org Subject: [PATCH v2 2/2] ath10k: add hw connection monitor support Date: Mon, 9 Mar 2015 14:36:37 +0100 Message-Id: <1425908197-16118-2-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 1.8.5.3 In-Reply-To: <1425908197-16118-1-git-send-email-michal.kazior@tieto.com> References: <87fv9hyz2r.fsf@kamboji.qca.qualcomm.com> <1425908197-16118-1-git-send-email-michal.kazior@tieto.com> X-DomainID: tieto.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150309_063926_368479_1E6A121E X-CRM114-Status: GOOD ( 14.98 ) X-Spam-Score: -0.8 (/) Cc: linux-wireless@vger.kernel.org, Michal Kazior X-BeenThere: ath10k@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "ath10k" Errors-To: ath10k-bounces+patchwork-ath10k=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, 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 Some firmware revisions (e.g. qca6174 with fw73) don't deliver beacons to host reliably. This causes random disconnects even in perfect conditions. This is most visible with multi-channel operation. All available firmware revisions seem to support beacon miss offloading so there shouldn't be any problems. Signed-off-by: Michal Kazior --- Notes: v2: * conflict resolution hint: base of this patchset (af695a659c69d347948ceab2c562e208ba48b26e) doesn't include `ath10k: fix patching mistake for AP/IBSS CSA` yet. Whichever you apply first you'll end up with a conflict in ath10k_bss_disassoc(). Eventually the data_lock goes away from there. drivers/net/wireless/ath/ath10k/core.h | 2 + drivers/net/wireless/ath/ath10k/mac.c | 77 +++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/mac.h | 2 + drivers/net/wireless/ath/ath10k/wmi.c | 7 +++- 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 9b8f486..c1f43b0 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -43,6 +43,7 @@ #define ATH10K_SCAN_ID 0 #define WMI_READY_TIMEOUT (5 * HZ) #define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ) +#define ATH10K_CONNECTION_LOSS_HZ (3*HZ) #define ATH10K_NUM_CHANS 38 /* Antenna noise floor */ @@ -342,6 +343,7 @@ struct ath10k_vif { int txpower; struct wmi_wmm_params_all_arg wmm_params; struct work_struct ap_csa_work; + struct delayed_work connection_loss_work; }; struct ath10k_vif_iter { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 1138f4f..d672e05 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1503,6 +1503,75 @@ static void ath10k_mac_vif_ap_csa_work(struct work_struct *work) mutex_unlock(&ar->conf_mutex); } +static void ath10k_mac_handle_beacon_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct sk_buff *skb = data; + struct ieee80211_mgmt *mgmt = (void *)skb->data; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + + if (vif->type != NL80211_IFTYPE_STATION) + return; + + if (!ether_addr_equal(mgmt->bssid, vif->bss_conf.bssid)) + return; + + cancel_delayed_work(&arvif->connection_loss_work); +} + +void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb) +{ + ieee80211_iterate_active_interfaces_atomic(ar->hw, + IEEE80211_IFACE_ITER_NORMAL, + ath10k_mac_handle_beacon_iter, + skb); +} + +static void ath10k_mac_handle_beacon_miss_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + u32 *vdev_id = data; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k *ar = arvif->ar; + struct ieee80211_hw *hw = ar->hw; + + if (arvif->vdev_id != *vdev_id) + return; + + if (!arvif->is_up) + return; + + ieee80211_beacon_loss(vif); + + /* Firmware doesn't report beacon loss events repeatedly. If AP probe + * (done by mac80211) succeeds but beacons do not resume then it + * doesn't make sense to continue operation. Queue connection loss work + * which can be cancelled when beacon is received. + */ + ieee80211_queue_delayed_work(hw, &arvif->connection_loss_work, + ATH10K_CONNECTION_LOSS_HZ); +} + +void ath10k_mac_handle_beacon_miss(struct ath10k *ar, u32 vdev_id) +{ + ieee80211_iterate_active_interfaces_atomic(ar->hw, + IEEE80211_IFACE_ITER_NORMAL, + ath10k_mac_handle_beacon_miss_iter, + &vdev_id); +} + +static void ath10k_mac_vif_sta_connection_loss_work(struct work_struct *work) +{ + struct ath10k_vif *arvif = container_of(work, struct ath10k_vif, + connection_loss_work.work); + struct ieee80211_vif *vif = arvif->vif; + + if (!arvif->is_up) + return; + + ieee80211_connection_loss(vif); +} + /**********************/ /* Station management */ /**********************/ @@ -2139,6 +2208,8 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, spin_lock_bh(&arvif->ar->data_lock); arvif->is_up = false; spin_unlock_bh(&arvif->ar->data_lock); + + cancel_delayed_work_sync(&arvif->connection_loss_work); } static int ath10k_station_assoc(struct ath10k *ar, @@ -3377,6 +3448,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, INIT_LIST_HEAD(&arvif->list); INIT_WORK(&arvif->ap_csa_work, ath10k_mac_vif_ap_csa_work); + INIT_DELAYED_WORK(&arvif->connection_loss_work, + ath10k_mac_vif_sta_connection_loss_work); if (ar->free_vdev_map == 0) { ath10k_warn(ar, "Free vdev map is empty, no more interfaces allowed.\n"); @@ -3595,6 +3668,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, int ret; cancel_work_sync(&arvif->ap_csa_work); + cancel_delayed_work_sync(&arvif->connection_loss_work); mutex_lock(&ar->conf_mutex); @@ -5726,7 +5800,8 @@ int ath10k_mac_register(struct ath10k *ar) IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_AP_LINK_PS | IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_SW_CRYPTO_CONTROL; + IEEE80211_HW_SW_CRYPTO_CONTROL | + IEEE80211_HW_CONNECTION_MONITOR; ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS; diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 6829611..3b64d99 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -45,6 +45,8 @@ void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif); void ath10k_drain_tx(struct ath10k *ar); bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr, u8 keyidx); +void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb); +void ath10k_mac_handle_beacon_miss(struct ath10k *ar, u32 vdev_id); static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 58719d8..54430a1 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1586,6 +1586,9 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) } } + if (ieee80211_is_beacon(hdr->frame_control)) + ath10k_mac_handle_beacon(ar, skb); + ath10k_dbg(ar, ATH10K_DBG_MGMT, "event mgmt rx skb %p len %d ftype %02x stype %02x\n", skb, skb->len, @@ -2815,8 +2818,10 @@ void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb) reason, vdev_id); switch (reason) { - case WMI_ROAM_REASON_BETTER_AP: case WMI_ROAM_REASON_BEACON_MISS: + ath10k_mac_handle_beacon_miss(ar, vdev_id); + break; + case WMI_ROAM_REASON_BETTER_AP: case WMI_ROAM_REASON_LOW_RSSI: case WMI_ROAM_REASON_SUITABLE_AP_FOUND: case WMI_ROAM_REASON_HO_FAILED: