* [PATCHv2 7/7] ath10k: remove wmi event worker thread
From: Michal Kazior @ 2013-09-13 12:16 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1379074618-30534-1-git-send-email-michal.kazior@tieto.com>
It's not really necessary to have this processed
in a worker. There are no sleepable calls (and
actually shouldn't be).
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/core.h | 3 ---
drivers/net/wireless/ath/ath10k/wmi.c | 44 +-------------------------------
2 files changed, 1 insertion(+), 46 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index c2b6a76..fcf94ee 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -113,9 +113,6 @@ struct ath10k_wmi {
struct completion service_ready;
struct completion unified_ready;
wait_queue_head_t tx_credits_wq;
-
- struct sk_buff_head wmi_event_list;
- struct work_struct wmi_event_work;
};
struct ath10k_peer_stat {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index b29d2b9..6803ead 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1055,7 +1055,7 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb)
return 0;
}
-static void ath10k_wmi_event_process(struct ath10k *ar, struct sk_buff *skb)
+static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
enum wmi_event_id id;
@@ -1174,43 +1174,6 @@ static void ath10k_wmi_event_process(struct ath10k *ar, struct sk_buff *skb)
dev_kfree_skb(skb);
}
-static void ath10k_wmi_event_work(struct work_struct *work)
-{
- struct ath10k *ar = container_of(work, struct ath10k,
- wmi.wmi_event_work);
- struct sk_buff *skb;
-
- for (;;) {
- skb = skb_dequeue(&ar->wmi.wmi_event_list);
- if (!skb)
- break;
-
- ath10k_wmi_event_process(ar, skb);
- }
-}
-
-static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
-{
- struct wmi_cmd_hdr *cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
- enum wmi_event_id event_id;
-
- event_id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
-
- /* some events require to be handled ASAP
- * thus can't be defered to a worker thread */
- switch (event_id) {
- case WMI_MGMT_RX_EVENTID:
- case WMI_HOST_SWBA_EVENTID:
- ath10k_wmi_event_process(ar, skb);
- return;
- default:
- break;
- }
-
- skb_queue_tail(&ar->wmi.wmi_event_list, skb);
- queue_work(ar->workqueue, &ar->wmi.wmi_event_work);
-}
-
/* WMI Initialization functions */
int ath10k_wmi_attach(struct ath10k *ar)
{
@@ -1218,16 +1181,11 @@ int ath10k_wmi_attach(struct ath10k *ar)
init_completion(&ar->wmi.unified_ready);
init_waitqueue_head(&ar->wmi.tx_credits_wq);
- skb_queue_head_init(&ar->wmi.wmi_event_list);
- INIT_WORK(&ar->wmi.wmi_event_work, ath10k_wmi_event_work);
-
return 0;
}
void ath10k_wmi_detach(struct ath10k *ar)
{
- cancel_work_sync(&ar->wmi.wmi_event_work);
- skb_queue_purge(&ar->wmi.wmi_event_list);
}
int ath10k_wmi_connect_htc_service(struct ath10k *ar)
--
1.7.9.5
^ permalink raw reply related
* [PATCHv2 6/7] ath10k: remove wmi pending count limit
From: Michal Kazior @ 2013-09-13 12:16 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1379074618-30534-1-git-send-email-michal.kazior@tieto.com>
It is no longer used nor necessary since WMI
commands can block.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/core.h | 2 --
drivers/net/wireless/ath/ath10k/mac.c | 9 ---------
drivers/net/wireless/ath/ath10k/wmi.c | 32 --------------------------------
drivers/net/wireless/ath/ath10k/wmi.h | 2 --
4 files changed, 45 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 14b7d3d..c2b6a76 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -112,8 +112,6 @@ struct ath10k_wmi {
enum ath10k_htc_ep_id eid;
struct completion service_ready;
struct completion unified_ready;
- atomic_t pending_tx_count;
- wait_queue_head_t wq;
wait_queue_head_t tx_credits_wq;
struct sk_buff_head wmi_event_list;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 6c3e9d1..11aa13e 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1224,8 +1224,6 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
/* FIXME: why don't we print error if wmi call fails? */
ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
- ath10k_wmi_flush_tx(ar);
-
arvif->def_wep_key_index = 0;
}
@@ -1664,8 +1662,6 @@ static int ath10k_abort_scan(struct ath10k *ar)
return -EIO;
}
- ath10k_wmi_flush_tx(ar);
-
ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ);
if (ret == 0)
ath10k_warn("timed out while waiting for scan to stop\n");
@@ -1699,10 +1695,6 @@ static int ath10k_start_scan(struct ath10k *ar,
if (ret)
return ret;
- /* make sure we submit the command so the completion
- * timeout makes sense */
- ath10k_wmi_flush_tx(ar);
-
ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ);
if (ret == 0) {
ath10k_abort_scan(ar);
@@ -1924,7 +1916,6 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
ret = ath10k_monitor_destroy(ar);
}
- ath10k_wmi_flush_tx(ar);
mutex_unlock(&ar->conf_mutex);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 9152dae..b29d2b9 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -23,30 +23,6 @@
#include "wmi.h"
#include "mac.h"
-void ath10k_wmi_flush_tx(struct ath10k *ar)
-{
- int ret;
-
- lockdep_assert_held(&ar->conf_mutex);
-
- if (ar->state == ATH10K_STATE_WEDGED) {
- ath10k_warn("wmi flush skipped - device is wedged anyway\n");
- return;
- }
-
- ret = wait_event_timeout(ar->wmi.wq,
- atomic_read(&ar->wmi.pending_tx_count) == 0,
- 5*HZ);
- if (atomic_read(&ar->wmi.pending_tx_count) == 0)
- return;
-
- if (ret == 0)
- ret = -ETIMEDOUT;
-
- if (ret < 0)
- ath10k_warn("wmi flush failed (%d)\n", ret);
-}
-
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
{
int ret;
@@ -85,9 +61,6 @@ static struct sk_buff *ath10k_wmi_alloc_skb(u32 len)
static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
{
dev_kfree_skb(skb);
-
- if (atomic_sub_return(1, &ar->wmi.pending_tx_count) == 0)
- wake_up(&ar->wmi.wq);
}
static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
@@ -1243,7 +1216,6 @@ int ath10k_wmi_attach(struct ath10k *ar)
{
init_completion(&ar->wmi.service_ready);
init_completion(&ar->wmi.unified_ready);
- init_waitqueue_head(&ar->wmi.wq);
init_waitqueue_head(&ar->wmi.tx_credits_wq);
skb_queue_head_init(&ar->wmi.wmi_event_list);
@@ -1254,10 +1226,6 @@ int ath10k_wmi_attach(struct ath10k *ar)
void ath10k_wmi_detach(struct ath10k *ar)
{
- /* HTC should've drained the packets already */
- if (WARN_ON(atomic_read(&ar->wmi.pending_tx_count) > 0))
- ath10k_warn("there are still pending packets\n");
-
cancel_work_sync(&ar->wmi.wmi_event_work);
skb_queue_purge(&ar->wmi.wmi_event_list);
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index b100431..2c52c23 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3044,7 +3044,6 @@ struct wmi_force_fw_hang_cmd {
#define WMI_MAX_EVENT 0x1000
/* Maximum number of pending TXed WMI packets */
-#define WMI_MAX_PENDING_TX_COUNT 128
#define WMI_SKB_HEADROOM sizeof(struct wmi_cmd_hdr)
/* By default disable power save for IBSS */
@@ -3057,7 +3056,6 @@ int ath10k_wmi_attach(struct ath10k *ar);
void ath10k_wmi_detach(struct ath10k *ar);
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
-void ath10k_wmi_flush_tx(struct ath10k *ar);
int ath10k_wmi_connect_htc_service(struct ath10k *ar);
int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
--
1.7.9.5
^ permalink raw reply related
* [PATCHv2 5/7] ath10k: improve beacon submission latency
From: Michal Kazior @ 2013-09-13 12:16 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1379074618-30534-1-git-send-email-michal.kazior@tieto.com>
The patch prevents beacon misses in some case of
heavy load on a system.
If a beacon can't be transmitted directly from an
SWBA event it will be left in arvif->beacon and
transmission will be retried once TX credits
become available.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
v2:
* add comments on ath10k_wmi_tx_beacons_nowait() usage
drivers/net/wireless/ath/ath10k/core.h | 1 +
drivers/net/wireless/ath/ath10k/mac.c | 7 +++
drivers/net/wireless/ath/ath10k/wmi.c | 74 ++++++++++++++++++++++++++------
drivers/net/wireless/ath/ath10k/wmi.h | 3 +-
4 files changed, 71 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index c953a33..14b7d3d 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -204,6 +204,7 @@ struct ath10k_vif {
enum wmi_vdev_subtype vdev_subtype;
u32 beacon_interval;
u32 dtim_period;
+ struct sk_buff *beacon;
struct ath10k *ar;
struct ieee80211_vif *vif;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 8b9fb66..6c3e9d1 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2075,6 +2075,13 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
+ spin_lock_bh(&ar->data_lock);
+ if (arvif->beacon) {
+ dev_kfree_skb_any(arvif->beacon);
+ arvif->beacon = NULL;
+ }
+ spin_unlock_bh(&ar->data_lock);
+
ar->free_vdev_map |= 1 << (arvif->vdev_id);
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index ff407c2..9152dae 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -120,8 +120,53 @@ err_pull:
return ret;
}
+static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
+{
+ struct wmi_bcn_tx_arg arg = {0};
+ int ret;
+
+ lockdep_assert_held(&arvif->ar->data_lock);
+
+ if (arvif->beacon == NULL)
+ return;
+
+ arg.vdev_id = arvif->vdev_id;
+ arg.tx_rate = 0;
+ arg.tx_power = 0;
+ arg.bcn = arvif->beacon->data;
+ arg.bcn_len = arvif->beacon->len;
+
+ ret = ath10k_wmi_beacon_send_nowait(arvif->ar, &arg);
+ if (ret)
+ return;
+
+ dev_kfree_skb_any(arvif->beacon);
+ arvif->beacon = NULL;
+}
+
+static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+
+ ath10k_wmi_tx_beacon_nowait(arvif);
+}
+
+static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar)
+{
+ spin_lock_bh(&ar->data_lock);
+ ieee80211_iterate_active_interfaces_atomic(ar->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ ath10k_wmi_tx_beacons_iter,
+ NULL);
+ spin_unlock_bh(&ar->data_lock);
+}
+
static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
{
+ /* try to send pending beacons first. they take priority */
+ ath10k_wmi_tx_beacons_nowait(ar);
+
wake_up(&ar->wmi.tx_credits_wq);
}
@@ -131,6 +176,9 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
int ret = -EINVAL;
wait_event_timeout(ar->wmi.tx_credits_wq, ({
+ /* try to send pending beacons first. they take priority */
+ ath10k_wmi_tx_beacons_nowait(ar);
+
ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
(ret != -EAGAIN);
}), 3*HZ);
@@ -760,10 +808,8 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
int i = -1;
struct wmi_bcn_info *bcn_info;
struct ath10k_vif *arvif;
- struct wmi_bcn_tx_arg arg;
struct sk_buff *bcn;
int vdev_id = 0;
- int ret;
ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n");
@@ -820,17 +866,17 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info);
ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info);
- arg.vdev_id = arvif->vdev_id;
- arg.tx_rate = 0;
- arg.tx_power = 0;
- arg.bcn = bcn->data;
- arg.bcn_len = bcn->len;
+ spin_lock_bh(&ar->data_lock);
+ if (arvif->beacon) {
+ ath10k_warn("SWBA overrun on vdev %d\n",
+ arvif->vdev_id);
+ dev_kfree_skb_any(arvif->beacon);
+ }
- ret = ath10k_wmi_beacon_send(ar, &arg);
- if (ret)
- ath10k_warn("could not send beacon (%d)\n", ret);
+ arvif->beacon = bcn;
- dev_kfree_skb_any(bcn);
+ ath10k_wmi_tx_beacon_nowait(arvif);
+ spin_unlock_bh(&ar->data_lock);
}
}
@@ -1181,6 +1227,7 @@ static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
* thus can't be defered to a worker thread */
switch (event_id) {
case WMI_MGMT_RX_EVENTID:
+ case WMI_HOST_SWBA_EVENTID:
ath10k_wmi_event_process(ar, skb);
return;
default:
@@ -2138,7 +2185,8 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar,
return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_ASSOC_CMDID);
}
-int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg)
+int ath10k_wmi_beacon_send_nowait(struct ath10k *ar,
+ const struct wmi_bcn_tx_arg *arg)
{
struct wmi_bcn_tx_cmd *cmd;
struct sk_buff *skb;
@@ -2154,7 +2202,7 @@ int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg)
cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len);
memcpy(cmd->bcn, arg->bcn, arg->bcn_len);
- return ath10k_wmi_cmd_send(ar, skb, WMI_BCN_TX_CMDID);
+ return ath10k_wmi_cmd_send_nowait(ar, skb, WMI_BCN_TX_CMDID);
}
static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index ab46582..b100431 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3110,7 +3110,8 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
enum wmi_ap_ps_peer_param param_id, u32 value);
int ath10k_wmi_scan_chan_list(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg);
-int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg);
+int ath10k_wmi_beacon_send_nowait(struct ath10k *ar,
+ const struct wmi_bcn_tx_arg *arg);
int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg);
int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);
--
1.7.9.5
^ permalink raw reply related
* [PATCHv2 4/7] ath10k: simplify HTC command submitting
From: Michal Kazior @ 2013-09-13 12:16 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1379074618-30534-1-git-send-email-michal.kazior@tieto.com>
The patch removes HTC endpoint tx workers in
favour of direct command submission. This makes a
lot more sense for data path.
mac80211 queues are effectively stopped/woken up
in a more timely fashion preventing build up of
frames. It's possible to push more traffic than
the device/system is able to handle and have no
hiccups or performance degradation with UDP
traffic.
WMI commands will now report errors properly and
possibly block as they actively can wait for tx
credits to become available.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
v2:
* use DIV_ROUND_UP
drivers/net/wireless/ath/ath10k/htc.c | 176 ++++++++-------------------------
drivers/net/wireless/ath/ath10k/htc.h | 4 -
drivers/net/wireless/ath/ath10k/wmi.c | 3 +-
3 files changed, 43 insertions(+), 140 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 49da4e5..d0d7212 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -117,99 +117,13 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
spin_unlock_bh(&ep->htc->tx_lock);
}
-static int ath10k_htc_issue_skb(struct ath10k_htc *htc,
- struct ath10k_htc_ep *ep,
- struct sk_buff *skb,
- u8 credits)
-{
- struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
- int ret;
-
- ath10k_dbg(ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__,
- ep->eid, skb);
-
- ath10k_htc_prepare_tx_skb(ep, skb);
-
- ret = ath10k_skb_map(htc->ar->dev, skb);
- if (ret)
- goto err;
-
- ret = ath10k_hif_send_head(htc->ar,
- ep->ul_pipe_id,
- ep->eid,
- skb->len,
- skb);
- if (unlikely(ret))
- goto err;
-
- return 0;
-err:
- ath10k_warn("HTC issue failed: %d\n", ret);
-
- spin_lock_bh(&htc->tx_lock);
- ep->tx_credits += credits;
- spin_unlock_bh(&htc->tx_lock);
-
- if (ep->ep_ops.ep_tx_credits)
- ep->ep_ops.ep_tx_credits(htc->ar);
-
- /* this is the simplest way to handle out-of-resources for non-credit
- * based endpoints. credit based endpoints can still get -ENOSR, but
- * this is highly unlikely as credit reservation should prevent that */
- if (ret == -ENOSR) {
- spin_lock_bh(&htc->tx_lock);
- __skb_queue_head(&ep->tx_queue, skb);
- spin_unlock_bh(&htc->tx_lock);
-
- return ret;
- }
-
- skb_cb->is_aborted = true;
- ath10k_htc_notify_tx_completion(ep, skb);
-
- return ret;
-}
-
-static void ath10k_htc_send_work(struct work_struct *work)
-{
- struct ath10k_htc_ep *ep = container_of(work,
- struct ath10k_htc_ep, send_work);
- struct ath10k_htc *htc = ep->htc;
- struct sk_buff *skb;
- u8 credits = 0;
- int ret;
-
- while (true) {
- if (ep->ul_is_polled)
- ath10k_htc_send_complete_check(ep, 0);
-
- spin_lock_bh(&htc->tx_lock);
- skb = __skb_dequeue(&ep->tx_queue);
-
- if (ep->tx_credit_flow_enabled) {
- credits = DIV_ROUND_UP(skb->len,
- htc->target_credit_size);
- if (ep->tx_credits < credits) {
- __skb_queue_head(&ep->tx_queue, skb);
- skb = NULL;
- }
- }
- spin_unlock_bh(&htc->tx_lock);
-
- if (!skb)
- break;
-
- ret = ath10k_htc_issue_skb(htc, ep, skb, credits);
- if (ret == -ENOSR)
- break;
- }
-}
-
int ath10k_htc_send(struct ath10k_htc *htc,
enum ath10k_htc_ep_id eid,
struct sk_buff *skb)
{
struct ath10k_htc_ep *ep = &htc->endpoint[eid];
+ int credits = 0;
+ int ret;
if (htc->ar->state == ATH10K_STATE_WEDGED)
return -ECOMM;
@@ -219,18 +133,55 @@ int ath10k_htc_send(struct ath10k_htc *htc,
return -ENOENT;
}
+ /* FIXME: This looks ugly, can we fix it? */
spin_lock_bh(&htc->tx_lock);
if (htc->stopped) {
spin_unlock_bh(&htc->tx_lock);
return -ESHUTDOWN;
}
+ spin_unlock_bh(&htc->tx_lock);
- __skb_queue_tail(&ep->tx_queue, skb);
skb_push(skb, sizeof(struct ath10k_htc_hdr));
- spin_unlock_bh(&htc->tx_lock);
- queue_work(htc->ar->workqueue, &ep->send_work);
+ if (ep->tx_credit_flow_enabled) {
+ credits = DIV_ROUND_UP(skb->len, htc->target_credit_size);
+ spin_lock_bh(&htc->tx_lock);
+ if (ep->tx_credits < credits) {
+ spin_unlock_bh(&htc->tx_lock);
+ ret = -EAGAIN;
+ goto err_pull;
+ }
+ ep->tx_credits -= credits;
+ spin_unlock_bh(&htc->tx_lock);
+ }
+
+ ath10k_htc_prepare_tx_skb(ep, skb);
+
+ ret = ath10k_skb_map(htc->ar->dev, skb);
+ if (ret)
+ goto err_credits;
+
+ ret = ath10k_hif_send_head(htc->ar, ep->ul_pipe_id, ep->eid,
+ skb->len, skb);
+ if (ret)
+ goto err_unmap;
+
return 0;
+
+err_unmap:
+ ath10k_skb_unmap(htc->ar->dev, skb);
+err_credits:
+ if (ep->tx_credit_flow_enabled) {
+ spin_lock_bh(&htc->tx_lock);
+ ep->tx_credits += credits;
+ spin_unlock_bh(&htc->tx_lock);
+
+ if (ep->ep_ops.ep_tx_credits)
+ ep->ep_ops.ep_tx_credits(htc->ar);
+ }
+err_pull:
+ skb_pull(skb, sizeof(struct ath10k_htc_hdr));
+ return ret;
}
static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
@@ -243,39 +194,9 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
ath10k_htc_notify_tx_completion(ep, skb);
/* the skb now belongs to the completion handler */
- /* note: when using TX credit flow, the re-checking of queues happens
- * when credits flow back from the target. in the non-TX credit case,
- * we recheck after the packet completes */
- spin_lock_bh(&htc->tx_lock);
- if (!ep->tx_credit_flow_enabled && !htc->stopped)
- queue_work(ar->workqueue, &ep->send_work);
- spin_unlock_bh(&htc->tx_lock);
-
return 0;
}
-/* flush endpoint TX queue */
-static void ath10k_htc_flush_endpoint_tx(struct ath10k_htc *htc,
- struct ath10k_htc_ep *ep)
-{
- struct sk_buff *skb;
- struct ath10k_skb_cb *skb_cb;
-
- spin_lock_bh(&htc->tx_lock);
- for (;;) {
- skb = __skb_dequeue(&ep->tx_queue);
- if (!skb)
- break;
-
- skb_cb = ATH10K_SKB_CB(skb);
- skb_cb->is_aborted = true;
- ath10k_htc_notify_tx_completion(ep, skb);
- }
- spin_unlock_bh(&htc->tx_lock);
-
- cancel_work_sync(&ep->send_work);
-}
-
/***********/
/* Receive */
/***********/
@@ -310,9 +231,6 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc,
ep->ep_ops.ep_tx_credits(htc->ar);
spin_lock_bh(&htc->tx_lock);
}
-
- if (ep->tx_credits && !skb_queue_empty(&ep->tx_queue))
- queue_work(htc->ar->workqueue, &ep->send_work);
}
spin_unlock_bh(&htc->tx_lock);
}
@@ -570,10 +488,8 @@ static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc)
ep->max_ep_message_len = 0;
ep->max_tx_queue_depth = 0;
ep->eid = i;
- skb_queue_head_init(&ep->tx_queue);
ep->htc = htc;
ep->tx_credit_flow_enabled = true;
- INIT_WORK(&ep->send_work, ath10k_htc_send_work);
}
}
@@ -916,18 +832,10 @@ int ath10k_htc_start(struct ath10k_htc *htc)
*/
void ath10k_htc_stop(struct ath10k_htc *htc)
{
- int i;
- struct ath10k_htc_ep *ep;
-
spin_lock_bh(&htc->tx_lock);
htc->stopped = true;
spin_unlock_bh(&htc->tx_lock);
- for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
- ep = &htc->endpoint[i];
- ath10k_htc_flush_endpoint_tx(htc, ep);
- }
-
ath10k_hif_stop(htc->ar);
}
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index 92ca29b..4716d33 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -316,15 +316,11 @@ struct ath10k_htc_ep {
int ul_is_polled; /* call HIF to get tx completions */
int dl_is_polled; /* call HIF to fetch rx (not implemented) */
- struct sk_buff_head tx_queue;
-
u8 seq_no; /* for debugging */
int tx_credits;
int tx_credit_size;
int tx_credits_per_max_message;
bool tx_credit_flow_enabled;
-
- struct work_struct send_work;
};
struct ath10k_htc_svc_tx_credits {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 66cd892..ff407c2 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -120,8 +120,7 @@ err_pull:
return ret;
}
-static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar,
- enum ath10k_htc_ep_id eid)
+static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
{
wake_up(&ar->wmi.tx_credits_wq);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCHv2 3/7] ath10k: make WMI commands block by design
From: Michal Kazior @ 2013-09-13 12:16 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1379074618-30534-1-git-send-email-michal.kazior@tieto.com>
This will be necessary for further changes in
command submission scheme.
Once HTC is cleaned up WMI commands will finally
block.
This requires for SWBA to be processed in a
non-atomic context for now. Once other necessary
changes are in this will be reverted.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/core.h | 1 +
drivers/net/wireless/ath/ath10k/trace.h | 11 ++++---
drivers/net/wireless/ath/ath10k/wmi.c | 54 +++++++++++++++++++------------
3 files changed, 42 insertions(+), 24 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 22b17d6..c953a33 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -114,6 +114,7 @@ struct ath10k_wmi {
struct completion unified_ready;
atomic_t pending_tx_count;
wait_queue_head_t wq;
+ wait_queue_head_t tx_credits_wq;
struct sk_buff_head wmi_event_list;
struct work_struct wmi_event_work;
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h
index bf1ceb8..fd53130 100644
--- a/drivers/net/wireless/ath/ath10k/trace.h
+++ b/drivers/net/wireless/ath/ath10k/trace.h
@@ -111,26 +111,29 @@ TRACE_EVENT(ath10k_log_dbg_dump,
);
TRACE_EVENT(ath10k_wmi_cmd,
- TP_PROTO(int id, void *buf, size_t buf_len),
+ TP_PROTO(int id, void *buf, size_t buf_len, int ret),
- TP_ARGS(id, buf, buf_len),
+ TP_ARGS(id, buf, buf_len, ret),
TP_STRUCT__entry(
__field(unsigned int, id)
__field(size_t, buf_len)
__dynamic_array(u8, buf, buf_len)
+ __field(int ret)
),
TP_fast_assign(
__entry->id = id;
__entry->buf_len = buf_len;
+ __entry->ret = ret;
memcpy(__get_dynamic_array(buf), buf, buf_len);
),
TP_printk(
- "id %d len %zu",
+ "id %d len %zu ret %d",
__entry->id,
- __entry->buf_len
+ __entry->buf_len,
+ __entry->ret
)
);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 32fd5e7..66cd892 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -90,13 +90,12 @@ static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
wake_up(&ar->wmi.wq);
}
-/* WMI command API */
-static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
- enum wmi_cmd_id cmd_id)
+static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
+ enum wmi_cmd_id cmd_id)
{
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
struct wmi_cmd_hdr *cmd_hdr;
- int status;
+ int ret;
u32 cmd = 0;
if (skb_push(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
@@ -107,26 +106,40 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
cmd_hdr->cmd_id = __cpu_to_le32(cmd);
- if (atomic_add_return(1, &ar->wmi.pending_tx_count) >
- WMI_MAX_PENDING_TX_COUNT) {
- /* avoid using up memory when FW hangs */
- dev_kfree_skb(skb);
- atomic_dec(&ar->wmi.pending_tx_count);
- return -EBUSY;
- }
-
memset(skb_cb, 0, sizeof(*skb_cb));
+ ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb);
+ trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len, ret);
- trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len);
+ if (ret)
+ goto err_pull;
- status = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb);
- if (status) {
+ return 0;
+
+err_pull:
+ skb_pull(skb, sizeof(struct wmi_cmd_hdr));
+ return ret;
+}
+
+static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar,
+ enum ath10k_htc_ep_id eid)
+{
+ wake_up(&ar->wmi.tx_credits_wq);
+}
+
+static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
+ enum wmi_cmd_id cmd_id)
+{
+ int ret = -EINVAL;
+
+ wait_event_timeout(ar->wmi.tx_credits_wq, ({
+ ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
+ (ret != -EAGAIN);
+ }), 3*HZ);
+
+ if (ret)
dev_kfree_skb_any(skb);
- atomic_dec(&ar->wmi.pending_tx_count);
- return status;
- }
- return 0;
+ return ret;
}
static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
@@ -1168,7 +1181,6 @@ static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
/* some events require to be handled ASAP
* thus can't be defered to a worker thread */
switch (event_id) {
- case WMI_HOST_SWBA_EVENTID:
case WMI_MGMT_RX_EVENTID:
ath10k_wmi_event_process(ar, skb);
return;
@@ -1186,6 +1198,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
init_completion(&ar->wmi.service_ready);
init_completion(&ar->wmi.unified_ready);
init_waitqueue_head(&ar->wmi.wq);
+ init_waitqueue_head(&ar->wmi.tx_credits_wq);
skb_queue_head_init(&ar->wmi.wmi_event_list);
INIT_WORK(&ar->wmi.wmi_event_work, ath10k_wmi_event_work);
@@ -1215,6 +1228,7 @@ int ath10k_wmi_connect_htc_service(struct ath10k *ar)
/* these fields are the same for all service endpoints */
conn_req.ep_ops.ep_tx_complete = ath10k_wmi_htc_tx_complete;
conn_req.ep_ops.ep_rx_complete = ath10k_wmi_process_rx;
+ conn_req.ep_ops.ep_tx_credits = ath10k_wmi_op_ep_tx_credits;
/* connect to control service */
conn_req.service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL;
--
1.7.9.5
^ permalink raw reply related
* [PATCHv2 2/7] ath10k: add HTC TX credits replenishing notification
From: Michal Kazior @ 2013-09-13 12:16 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1379074618-30534-1-git-send-email-michal.kazior@tieto.com>
This will allow higher layers to anticipate and
act upon TX credits renewal. This will be
important for some future rework of WMI command
submission.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/htc.c | 9 +++++++++
drivers/net/wireless/ath/ath10k/htc.h | 1 +
2 files changed, 10 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 1da0f82..49da4e5 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -150,6 +150,9 @@ err:
ep->tx_credits += credits;
spin_unlock_bh(&htc->tx_lock);
+ if (ep->ep_ops.ep_tx_credits)
+ ep->ep_ops.ep_tx_credits(htc->ar);
+
/* this is the simplest way to handle out-of-resources for non-credit
* based endpoints. credit based endpoints can still get -ENOSR, but
* this is highly unlikely as credit reservation should prevent that */
@@ -302,6 +305,12 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc,
ep = &htc->endpoint[report->eid];
ep->tx_credits += report->credits;
+ if (ep->ep_ops.ep_tx_credits) {
+ spin_unlock_bh(&htc->tx_lock);
+ ep->ep_ops.ep_tx_credits(htc->ar);
+ spin_lock_bh(&htc->tx_lock);
+ }
+
if (ep->tx_credits && !skb_queue_empty(&ep->tx_queue))
queue_work(htc->ar->workqueue, &ep->send_work);
}
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index e1dd8c7..92ca29b 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -276,6 +276,7 @@ struct ath10k_htc_ops {
struct ath10k_htc_ep_ops {
void (*ep_tx_complete)(struct ath10k *, struct sk_buff *);
void (*ep_rx_complete)(struct ath10k *, struct sk_buff *);
+ void (*ep_tx_credits)(struct ath10k *);
};
/* service connection information */
--
1.7.9.5
^ permalink raw reply related
* [PATCHv2 1/7] ath10k: simplify HTC credits calculation
From: Michal Kazior @ 2013-09-13 12:16 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1379074618-30534-1-git-send-email-michal.kazior@tieto.com>
Credit calculation was overly complex
unnecessarily. Now skb dequeing is more unified.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
v2:
* use DIV_ROUND_UP
drivers/net/wireless/ath/ath10k/htc.c | 58 ++++++---------------------------
1 file changed, 10 insertions(+), 48 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index f03fd8d..1da0f82 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -167,49 +167,6 @@ err:
return ret;
}
-static struct sk_buff *ath10k_htc_get_skb_credit_based(struct ath10k_htc *htc,
- struct ath10k_htc_ep *ep,
- u8 *credits)
-{
- struct sk_buff *skb;
- struct ath10k_skb_cb *skb_cb;
- int credits_required;
- int remainder;
- unsigned int transfer_len;
-
- lockdep_assert_held(&htc->tx_lock);
-
- skb = __skb_dequeue(&ep->tx_queue);
- if (!skb)
- return NULL;
-
- skb_cb = ATH10K_SKB_CB(skb);
- transfer_len = skb->len;
-
- if (likely(transfer_len <= htc->target_credit_size)) {
- credits_required = 1;
- } else {
- /* figure out how many credits this message requires */
- credits_required = transfer_len / htc->target_credit_size;
- remainder = transfer_len % htc->target_credit_size;
-
- if (remainder)
- credits_required++;
- }
-
- ath10k_dbg(ATH10K_DBG_HTC, "Credits required %d got %d\n",
- credits_required, ep->tx_credits);
-
- if (ep->tx_credits < credits_required) {
- __skb_queue_head(&ep->tx_queue, skb);
- return NULL;
- }
-
- ep->tx_credits -= credits_required;
- *credits = credits_required;
- return skb;
-}
-
static void ath10k_htc_send_work(struct work_struct *work)
{
struct ath10k_htc_ep *ep = container_of(work,
@@ -224,11 +181,16 @@ static void ath10k_htc_send_work(struct work_struct *work)
ath10k_htc_send_complete_check(ep, 0);
spin_lock_bh(&htc->tx_lock);
- if (ep->tx_credit_flow_enabled)
- skb = ath10k_htc_get_skb_credit_based(htc, ep,
- &credits);
- else
- skb = __skb_dequeue(&ep->tx_queue);
+ skb = __skb_dequeue(&ep->tx_queue);
+
+ if (ep->tx_credit_flow_enabled) {
+ credits = DIV_ROUND_UP(skb->len,
+ htc->target_credit_size);
+ if (ep->tx_credits < credits) {
+ __skb_queue_head(&ep->tx_queue, skb);
+ skb = NULL;
+ }
+ }
spin_unlock_bh(&htc->tx_lock);
if (!skb)
--
1.7.9.5
^ permalink raw reply related
* [PATCHv2 0/7] ath10k: improve TX path
From: Michal Kazior @ 2013-09-13 12:16 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1378821003-22925-1-git-send-email-michal.kazior@tieto.com>
Hi,
This patchset addresses two issues:
* system/userspace starvation on heavy briding
UDP TX
* unstable/inconsistent UDP TX throughput
In short the patchset simplifies TX path by
removing HTC TX workers, makes WMI commands block
and makes ath10k more responsive to queues
becoming full. This contributes to both improved
throughput and makes the system more responsive
under heavy UDP TX load.
Max stable briding TX (ath10k as TX):
UDP w/o patchset: 520mbps
UDP w/ patchset: 570mbps
TCP w/o patchset: 350mbps
TCP w/ patchset: 400mbps
Measured with two 2x2 cards, one acting as an AP
on AP135 board, the other as a STA on a core i5
laptop. The AP135 was passing traffic from a
station on LAN/eth1 to the STA/wlan0.
v2:
* use DIV_ROUND_UP
* comment usage of ath10k_wmi_tx_beacons_nowait
* additional check for tx_credits_flow_enabled
Michal Kazior (7):
ath10k: simplify HTC credits calculation
ath10k: add HTC TX credits replenishing notification
ath10k: make WMI commands block by design
ath10k: simplify HTC command submitting
ath10k: improve beacon submission latency
ath10k: remove wmi pending count limit
ath10k: remove wmi event worker thread
drivers/net/wireless/ath/ath10k/core.h | 7 +-
drivers/net/wireless/ath/ath10k/htc.c | 215 +++++++------------------------
drivers/net/wireless/ath/ath10k/htc.h | 5 +-
drivers/net/wireless/ath/ath10k/mac.c | 16 +--
drivers/net/wireless/ath/ath10k/trace.h | 11 +-
drivers/net/wireless/ath/ath10k/wmi.c | 201 ++++++++++++++---------------
drivers/net/wireless/ath/ath10k/wmi.h | 5 +-
7 files changed, 160 insertions(+), 300 deletions(-)
--
1.7.9.5
^ permalink raw reply
* WEP/WPA/WPA2 implementation in software
From: Prabhunath G @ 2013-09-13 11:53 UTC (permalink / raw)
To: linux-wireless, kernelnewbies
Dear All,
Suppose there is no hardware support for
encryption/decryption for Wi-Fi devices. Will the data be
encrypted/decrypted by software implementation. If yes, is it done at
the application level or at the kernel level (mac80211).
Kindly clarify.
If the question has to be rephrased, please do it
Regards,
Prabhunath G
^ permalink raw reply
* Re: [RFC 4/5] mac80211: add generic quiesce procedure
From: Stanislaw Gruszka @ 2013-09-13 11:26 UTC (permalink / raw)
To: Johannes Berg; +Cc: ilw, linux-wireless
In-Reply-To: <1379070837.14883.11.camel@jlt4.sipsolutions.net>
On Fri, Sep 13, 2013 at 01:13:57PM +0200, Johannes Berg wrote:
> On Fri, 2013-09-13 at 12:36 +0200, Stanislaw Gruszka wrote:
> > Add function ieee80211_quiesce() end export it to allow be used by
> > drivers. It is intended to be used before restart_hw to stop mac80211
> > timers/works . Reverse quiesce on ieee80211_reconfig().
>
> Why can't this be done inside restart_hw()?
iwlwifi stop device before call restart_hw() and we need to
quiesce before iwlwifi stop device (like done in patch 5).
Stanislaw
^ permalink raw reply
* Re: [RFC 4/5] mac80211: add generic quiesce procedure
From: Johannes Berg @ 2013-09-13 11:13 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: ilw, linux-wireless
In-Reply-To: <1379068568-27552-5-git-send-email-sgruszka@redhat.com>
On Fri, 2013-09-13 at 12:36 +0200, Stanislaw Gruszka wrote:
> Add function ieee80211_quiesce() end export it to allow be used by
> drivers. It is intended to be used before restart_hw to stop mac80211
> timers/works . Reverse quiesce on ieee80211_reconfig().
Why can't this be done inside restart_hw()?
johannes
^ permalink raw reply
* [RFC 5/5] iwlwifi: quiesce mac80211 before fw restart
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
In-Reply-To: <1379068568-27552-1-git-send-email-sgruszka@redhat.com>
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/iwlwifi/dvm/mac80211.c | 1 +
drivers/net/wireless/iwlwifi/dvm/main.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index cae4d31..e819e5b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -393,6 +393,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
error:
priv->wowlan = false;
+ ieee80211_quiesce(priv->hw);
iwlagn_prepare_restart(priv);
ieee80211_restart_hw(priv->hw);
out:
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 7aad766..2e0fbea 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -975,10 +975,12 @@ static void iwl_bg_restart(struct work_struct *data)
return;
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+ iwl_cancel_deferred_work(priv);
+ if (priv->mac80211_registered)
+ ieee80211_quiesce(priv->hw);
mutex_lock(&priv->mutex);
iwlagn_prepare_restart(priv);
mutex_unlock(&priv->mutex);
- iwl_cancel_deferred_work(priv);
if (priv->mac80211_registered)
ieee80211_restart_hw(priv->hw);
else
--
1.8.3.1
^ permalink raw reply related
* [RFC 2/5] Revert "mac80211: cleanup suspend/resume on ibss mode"
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
In-Reply-To: <1379068568-27552-1-git-send-email-sgruszka@redhat.com>
This reverts commit a61829437e68c8b2036cf5005ed0e875451c9120.
---
net/mac80211/ibss.c | 29 ++++++++++++++++++++++++++++-
net/mac80211/ieee80211_i.h | 4 ++++
2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index a12afe7..91d1b29 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1155,9 +1155,36 @@ static void ieee80211_ibss_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+ struct ieee80211_local *local = sdata->local;
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ if (local->quiescing) {
+ ifibss->timer_running = true;
+ return;
+ }
+
+ ieee80211_queue_work(&local->hw, &sdata->work);
+}
+
+#ifdef CONFIG_PM
+void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+
+ if (del_timer_sync(&ifibss->timer))
+ ifibss->timer_running = true;
+}
+
+void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+
+ if (ifibss->timer_running) {
+ add_timer(&ifibss->timer);
+ ifibss->timer_running = false;
+ }
}
+#endif
void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
{
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4b7ef89..96ac8f8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -492,6 +492,8 @@ struct ieee80211_if_ibss {
u32 basic_rates;
+ bool timer_running;
+
bool fixed_bssid;
bool fixed_channel;
bool privacy;
@@ -1329,6 +1331,8 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params);
int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
+void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata);
+void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
--
1.8.3.1
^ permalink raw reply related
* [RFC 4/5] mac80211: add generic quiesce procedure
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
In-Reply-To: <1379068568-27552-1-git-send-email-sgruszka@redhat.com>
Add function ieee80211_quiesce() end export it to allow be used by
drivers. It is intended to be used before restart_hw to stop mac80211
timers/works . Reverse quiesce on ieee80211_reconfig().
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
include/net/mac80211.h | 10 ++++++++++
net/mac80211/ibss.c | 2 --
net/mac80211/main.c | 33 +++++++++++++++++++++++++++++++++
net/mac80211/mesh.c | 2 --
net/mac80211/mlme.c | 2 --
net/mac80211/util.c | 19 ++++++++++++++++++-
6 files changed, 61 insertions(+), 7 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4be8785..a428ee7 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3054,6 +3054,16 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw);
void ieee80211_free_hw(struct ieee80211_hw *hw);
/**
+ * ieee80211_quiesce - quiesce hardware
+ *
+ * Call this function to stop pending mac80211 activities before
+ * restarting hardware by ieee80211_restart_hw().
+ *
+ * @hw: the hardware to quiesce
+ */
+void ieee80211_quiesce(struct ieee80211_hw *hw);
+
+/**
* ieee80211_restart_hw - restart hardware completely
*
* Call this function when the hardware was restarted for some reason
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 91d1b29..bf2b5a9 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1166,7 +1166,6 @@ static void ieee80211_ibss_timer(unsigned long data)
ieee80211_queue_work(&local->hw, &sdata->work);
}
-#ifdef CONFIG_PM
void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
@@ -1184,7 +1183,6 @@ void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata)
ifibss->timer_running = false;
}
}
-#endif
void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
{
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 21d5d44..978f364 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -263,6 +263,39 @@ static void ieee80211_restart_work(struct work_struct *work)
rtnl_unlock();
}
+/* return value indicates whether the driver should be further notified */
+void ieee80211_quiesce(struct ieee80211_hw *hw)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata;
+
+ local->quiescing = true;
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
+ ieee80211_sta_quiesce(sdata);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ ieee80211_ibss_quiesce(sdata);
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ ieee80211_mesh_quiesce(sdata);
+ break;
+ default:
+ break;
+ }
+
+ cancel_work_sync(&sdata->work);
+ }
+
+ local->quiescing = false;
+}
+EXPORT_SYMBOL(ieee80211_quiesce);
+
void ieee80211_restart_hw(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index e131293..b950d8d 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -624,7 +624,6 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
round_jiffies(TU_TO_EXP_TIME(interval)));
}
-#ifdef CONFIG_PM
void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
@@ -651,7 +650,6 @@ void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
add_timer(&ifmsh->mesh_path_root_timer);
ieee80211_mesh_root_setup(ifmsh);
}
-#endif
static int
ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b308855..66cec97 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3678,7 +3678,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
}
}
-#ifdef CONFIG_PM
void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -3742,7 +3741,6 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
ieee80211_restart_sta_timer(sdata);
mutex_unlock(&sdata->local->mtx);
}
-#endif
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index e1b34a1..ee5a0b4 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1742,11 +1742,28 @@ int ieee80211_reconfig(struct ieee80211_local *local)
list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata))
continue;
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
ieee80211_sta_restart(sdata);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ ieee80211_ibss_restart(sdata);
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ ieee80211_mesh_restart(sdata);
+ break;
+ default:
+ break;
+ }
}
mod_timer(&local->sta_cleanup, jiffies + 1);
+
+ mutex_lock(&local->sta_mtx);
+ list_for_each_entry(sta, &local->sta_list, list)
+ mesh_plink_restart(sta);
+ mutex_unlock(&local->sta_mtx);
#else
WARN_ON(1);
#endif
--
1.8.3.1
^ permalink raw reply related
* [RFC 3/5] Revert "mac80211: cleanup suspend/resume on managed mode"
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
In-Reply-To: <1379068568-27552-1-git-send-email-sgruszka@redhat.com>
This reverts commit 9b7d72c1041ec5b20b24af487a98f71d8ff1555e.
Conflicts:
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
---
net/mac80211/ieee80211_i.h | 3 +++
net/mac80211/mlme.c | 63 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 96ac8f8..c5878af 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -402,6 +402,7 @@ struct ieee80211_if_managed {
u16 aid;
+ unsigned long timers_running; /* used for quiesce/restart */
bool powersave; /* powersave requested for this iface */
bool broken_ap; /* AP is broken -- turn off powersave */
bool have_beacon;
@@ -1313,6 +1314,8 @@ void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata);
int ieee80211_max_network_latency(struct notifier_block *nb,
unsigned long data, void *dummy);
int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
+void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
+void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 86e4ad5..b308855 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -92,6 +92,9 @@ MODULE_PARM_DESC(probe_wait_ms,
*/
#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
+#define TMR_RUNNING_TIMER 0
+#define TMR_RUNNING_CHANSW 1
+
/*
* We can have multiple work items (and connection probing)
* scheduling this timer, but we need to take care to only
@@ -988,8 +991,14 @@ static void ieee80211_chswitch_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+ if (sdata->local->quiescing) {
+ set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
+ return;
+ }
- ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
+ ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
}
static void
@@ -1922,6 +1931,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
del_timer_sync(&sdata->u.mgd.timer);
del_timer_sync(&sdata->u.mgd.chswitch_timer);
+ sdata->u.mgd.timers_running = 0;
+
sdata->vif.bss_conf.dtim_period = 0;
sdata->vif.bss_conf.beacon_rate = NULL;
@@ -3315,8 +3326,15 @@ static void ieee80211_sta_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_local *local = sdata->local;
+
+ if (local->quiescing) {
+ set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
+ return;
+ }
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
@@ -3661,6 +3679,37 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
}
#ifdef CONFIG_PM
+void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+ /*
+ * Stop timers before deleting work items, as timers
+ * could race and re-add the work-items. They will be
+ * re-established on connection.
+ */
+ del_timer_sync(&ifmgd->conn_mon_timer);
+ del_timer_sync(&ifmgd->bcn_mon_timer);
+
+ /*
+ * we need to use atomic bitops for the running bits
+ * only because both timers might fire at the same
+ * time -- the code here is properly synchronised.
+ */
+
+ cancel_work_sync(&ifmgd->request_smps_work);
+
+ cancel_work_sync(&ifmgd->monitor_work);
+ cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+ cancel_work_sync(&ifmgd->csa_connection_drop_work);
+ if (del_timer_sync(&ifmgd->timer))
+ set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
+
+ if (del_timer_sync(&ifmgd->chswitch_timer))
+ set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
+ cancel_work_sync(&ifmgd->chswitch_work);
+}
+
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -3682,6 +3731,16 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
return;
}
sdata_unlock(sdata);
+
+ if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running))
+ add_timer(&ifmgd->timer);
+ if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
+ add_timer(&ifmgd->chswitch_timer);
+ ieee80211_sta_reset_beacon_monitor(sdata);
+
+ mutex_lock(&sdata->local->mtx);
+ ieee80211_restart_sta_timer(sdata);
+ mutex_unlock(&sdata->local->mtx);
}
#endif
--
1.8.3.1
^ permalink raw reply related
* [RFC 1/5] Revert "mac80211: cleanup suspend/resume on mesh mode"
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
In-Reply-To: <1379068568-27552-1-git-send-email-sgruszka@redhat.com>
This reverts commit 690205f18fd069898c70d743f498ba42798e5c4e.
---
net/mac80211/ieee80211_i.h | 2 ++
net/mac80211/mesh.c | 57 ++++++++++++++++++++++++++++++++++++++++++++--
net/mac80211/mesh.h | 12 ++++++++++
net/mac80211/mesh_plink.c | 27 +++++++++++++++++++++-
net/mac80211/sta_info.h | 2 ++
5 files changed, 97 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b618651..4b7ef89 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -543,6 +543,8 @@ struct ieee80211_if_mesh {
struct timer_list mesh_path_timer;
struct timer_list mesh_path_root_timer;
+ unsigned long timers_running;
+
unsigned long wrkq_flags;
unsigned long mbss_changed;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 707ac61..e131293 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -13,6 +13,10 @@
#include "ieee80211_i.h"
#include "mesh.h"
+#define TMR_RUNNING_HK 0
+#define TMR_RUNNING_MP 1
+#define TMR_RUNNING_MPR 2
+
static int mesh_allocated;
static struct kmem_cache *rm_cache;
@@ -46,6 +50,11 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
+ if (local->quiescing) {
+ set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
+ return;
+ }
+
ieee80211_queue_work(&local->hw, &sdata->work);
}
@@ -472,8 +481,15 @@ static void ieee80211_mesh_path_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ if (local->quiescing) {
+ set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
+ return;
+ }
+
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
static void ieee80211_mesh_path_root_timer(unsigned long data)
@@ -481,10 +497,16 @@ static void ieee80211_mesh_path_root_timer(unsigned long data)
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ if (local->quiescing) {
+ set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
+ return;
+ }
+
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
@@ -602,6 +624,35 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
round_jiffies(TU_TO_EXP_TIME(interval)));
}
+#ifdef CONFIG_PM
+void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+
+ /* use atomic bitops in case all timers fire at the same time */
+
+ if (del_timer_sync(&ifmsh->housekeeping_timer))
+ set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
+ if (del_timer_sync(&ifmsh->mesh_path_timer))
+ set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
+ if (del_timer_sync(&ifmsh->mesh_path_root_timer))
+ set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
+}
+
+void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+
+ if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running))
+ add_timer(&ifmsh->housekeeping_timer);
+ if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running))
+ add_timer(&ifmsh->mesh_path_timer);
+ if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running))
+ add_timer(&ifmsh->mesh_path_root_timer);
+ ieee80211_mesh_root_setup(ifmsh);
+}
+#endif
+
static int
ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
{
@@ -810,6 +861,8 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
local->fif_other_bss--;
atomic_dec(&local->iff_allmultis);
ieee80211_configure_filter(local);
+
+ sdata->u.mesh.timers_running = 0;
}
static void
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 2bc7fd2..6fd6ed6 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -315,6 +315,8 @@ void mesh_path_timer(unsigned long data);
void mesh_path_flush_by_nexthop(struct sta_info *sta);
void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
+void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
+void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
@@ -359,12 +361,22 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
+void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata);
+void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata);
+void mesh_plink_quiesce(struct sta_info *sta);
+void mesh_plink_restart(struct sta_info *sta);
void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
void ieee80211s_stop(void);
#else
static inline void
ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
+static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
+{}
+static inline void mesh_plink_quiesce(struct sta_info *sta) {}
+static inline void mesh_plink_restart(struct sta_info *sta) {}
static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
{ return false; }
static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 6b65d50..2b18cc6 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -540,8 +540,10 @@ static void mesh_plink_timer(unsigned long data)
*/
sta = (struct sta_info *) data;
- if (sta->sdata->local->quiescing)
+ if (sta->sdata->local->quiescing) {
+ sta->plink_timer_was_running = true;
return;
+ }
spin_lock_bh(&sta->lock);
if (sta->ignore_plink_timer) {
@@ -602,6 +604,29 @@ static void mesh_plink_timer(unsigned long data)
}
}
+#ifdef CONFIG_PM
+void mesh_plink_quiesce(struct sta_info *sta)
+{
+ if (!ieee80211_vif_is_mesh(&sta->sdata->vif))
+ return;
+
+ /* no kernel mesh sta timers have been initialized */
+ if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)
+ return;
+
+ if (del_timer_sync(&sta->plink_timer))
+ sta->plink_timer_was_running = true;
+}
+
+void mesh_plink_restart(struct sta_info *sta)
+{
+ if (sta->plink_timer_was_running) {
+ add_timer(&sta->plink_timer);
+ sta->plink_timer_was_running = false;
+ }
+}
+#endif
+
static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
{
sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 4208dbd..3e750c7 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -282,6 +282,7 @@ struct sta_ampdu_mlme {
* @plink_state: peer link state
* @plink_timeout: timeout of peer link
* @plink_timer: peer link watch timer
+ * @plink_timer_was_running: used by suspend/resume to restore timers
* @t_offset: timing offset relative to this host
* @t_offset_setpoint: reference timing offset of this sta to be used when
* calculating clockdrift
@@ -388,6 +389,7 @@ struct sta_info {
__le16 reason;
u8 plink_retries;
bool ignore_plink_timer;
+ bool plink_timer_was_running;
enum nl80211_plink_state plink_state;
u32 plink_timeout;
struct timer_list plink_timer;
--
1.8.3.1
^ permalink raw reply related
* [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
Here is continuation of short discussion I started here:
http://marc.info/?l=linux-wireless&m=137724899704012&w=2
I made patches which do quiesce and that can be used by iwlwifi
restart procedure to avoid calling iwlwifi methods by mac80211
while firmware is not alive.
But honestly, I'm not happy with that work. It does not fix root of the
problem (microcode errors/hangs) and seems to be just to much
complication to avoid warnings, which are consequence of firmware
malfunction. So I just prefer to remove WARN_ONCE(trans->state !=
IWL_TRANS_FW_ALIVE) and replace it by ordinary IWL_WARN(), which
does not generate auto bug reports.
Regarding firmware problems debugging, perhaps ftrace can be used
for that. iwlwifi has already tracing capabilities. Allow to gather
log using trace-cmd and call tracing_off() when firmware error will
happen, perhaps will allow to debug firmware problems efficiently.
If you think that's right we could add WARN_ONCE on firmware error
to have automatic bug reports. Then we could ask user for the trace
to debug and solve the issue. Would that work for you?
Stanislaw Gruszka (5):
Revert "mac80211: cleanup suspend/resume on mesh mode"
Revert "mac80211: cleanup suspend/resume on ibss mode"
Revert "mac80211: cleanup suspend/resume on managed mode"
mac80211: add generic quiesce procedure
iwlwifi: quiesce mac80211 before fw restart
drivers/net/wireless/iwlwifi/dvm/mac80211.c | 1 +
drivers/net/wireless/iwlwifi/dvm/main.c | 4 +-
include/net/mac80211.h | 10 +++++
net/mac80211/ibss.c | 27 +++++++++++-
net/mac80211/ieee80211_i.h | 9 ++++
net/mac80211/main.c | 33 +++++++++++++++
net/mac80211/mesh.c | 55 +++++++++++++++++++++++-
net/mac80211/mesh.h | 12 ++++++
net/mac80211/mesh_plink.c | 27 +++++++++++-
net/mac80211/mlme.c | 65 +++++++++++++++++++++++++++--
net/mac80211/sta_info.h | 2 +
net/mac80211/util.c | 19 ++++++++-
12 files changed, 254 insertions(+), 10 deletions(-)
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH] iwlwifi: do not dump stack whet triggering firmware restart
From: Stanislaw Gruszka @ 2013-09-13 9:31 UTC (permalink / raw)
To: Johannes Berg; +Cc: ilw, linux-wireless, emmanuel.grumbach
In-Reply-To: <1379063754.14883.10.camel@jlt4.sipsolutions.net>
On Fri, Sep 13, 2013 at 11:15:54AM +0200, Johannes Berg wrote:
> On Fri, 2013-09-13 at 10:45 +0200, Stanislaw Gruszka wrote:
> Hmm, we changed this code like below, is this still relevant?
Nope, please drop.
Stanislaw
^ permalink raw reply
* rtl8192cu: testing with EdiMax USB
From: Mark Cave-Ayland @ 2013-09-13 9:29 UTC (permalink / raw)
To: Larry Finger; +Cc: linux-wireless
Hi all,
So talking to some colleagues at work, I managed to find someone else
who uses the EdiMax USB dongle and persuaded them to lend it to me for
the weekend in order to see whether it could be related to a hardware
difference with my OEM dongle.
I've just tested with the EdiMax USB dongle which reports as "Bus 004
Device 004: ID 7392:7811 Edimax Technology Co., Ltd EW-7811Un 802.11n
Wireless Adapter [Realtek RTL8188CUS]" in lsusb, which I believe is
exactly the same hardware that Larry is using. And again I still see the
problem with disassociation.
I spent a bit more time tinkering further with debug=0x5, forgetting
that I had left your last diagnostic patch applied. Based upon when the
beacon output disappears in the logs (after updating the power
registers), it does seem likely that is a power-related problem.
The two power-related messages that stand out to me are:
1) Repeated output of "pHalData->bHwRadioOff and eRfPowerStateToSet do
not match: pHalData->bHwRadioOff 0, eRfPowerStateToSet 0" messages
2) rtl92c_dm_txpower_tracking_callback_thermalmeter() seems to be called
X seconds before the "AP off for X seconds" messages
Larry - I've sent you the complete debug off-list from the EdiMax, so it
should be a like-for-like comparison with your setup. Hopefully
comparing with your output will help you work out exactly what the
problem is.
ATB,
Mark.
^ permalink raw reply
* Re: [PATCH] iwlwifi: do not dump stack whet triggering firmware restart
From: Johannes Berg @ 2013-09-13 9:15 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: ilw, linux-wireless, emmanuel.grumbach
In-Reply-To: <1379061930-2007-1-git-send-email-sgruszka@redhat.com>
On Fri, 2013-09-13 at 10:45 +0200, Stanislaw Gruszka wrote:
> We send REPLY_ERROR command to the device to force microcode error
> and restart firmware. This is not a problem, so do not dump stack
> on such situation.
>
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> ---
> drivers/net/wireless/iwlwifi/pcie/tx.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
> index f45eb29..ec49033 100644
> --- a/drivers/net/wireless/iwlwifi/pcie/tx.c
> +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
> @@ -1546,7 +1546,8 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
> if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) {
> IWL_ERR(trans, "FW error in SYNC CMD %s\n",
> get_cmd_string(trans_pcie, cmd->id));
> - dump_stack();
> + if (cmd->id != REPLY_ERROR)
> + dump_stack();
Hmm, we changed this code like below, is this still relevant?
Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Date: Wed Sep 11 14:16:20 2013 +0300
iwlwifi: pcie: restart the driver when a command times out
This should really not happen. If it does, restarting is the
only way to recover since the driver and the firmware might
very well be out of sync. Moreover, iwl_op_mode_nic_error
will print data that might help debugging.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index d92baa7..32f179f 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1535,7 +1535,6 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
"Error sending %s: time out after %dms.\n",
get_cmd_string(trans_pcie, cmd->id),
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
- dump_stack();
IWL_ERR(trans,
"Current CMD queue read_ptr %d write_ptr %d\n",
@@ -1546,6 +1545,9 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
"Clearing HCMD_ACTIVE for command %s\n",
get_cmd_string(trans_pcie, cmd->id));
ret = -ETIMEDOUT;
+
+ iwl_op_mode_nic_error(trans->op_mode);
+
goto cancel;
}
}
johannes
^ permalink raw reply related
* Re: RTL8192CU continually reconnecting
From: Mark Cave-Ayland @ 2013-09-13 9:01 UTC (permalink / raw)
To: Larry Finger; +Cc: Timothy Rundle, linux-wireless
In-Reply-To: <5230CDF1.1040905@lwfinger.net>
On 11/09/13 21:09, Larry Finger wrote:
> I am now running a kernel built with your configuration. I needed to
> make a couple of changes as it did not have one of the modules my disk
> system needs, and nouveau caused kernel panics, but we are now
> operational. Outside of the whole system being slow due to only one 2.0
> GHz CPU, the wireless connection seems to be stable. At least, there
> have been no disconnects in the first half hour.
Thanks for testing Larry. Last night I finished building an SMP-capable
kernel with the same configuration and I see no change in behaviour. So
I think we can rule this out as a possible cause.
ATB,
Mark.
^ permalink raw reply
* [PATCH] iwlwifi: do not dump stack whet triggering firmware restart
From: Stanislaw Gruszka @ 2013-09-13 8:45 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
We send REPLY_ERROR command to the device to force microcode error
and restart firmware. This is not a problem, so do not dump stack
on such situation.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/iwlwifi/pcie/tx.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index f45eb29..ec49033 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1546,7 +1546,8 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) {
IWL_ERR(trans, "FW error in SYNC CMD %s\n",
get_cmd_string(trans_pcie, cmd->id));
- dump_stack();
+ if (cmd->id != REPLY_ERROR)
+ dump_stack();
ret = -EIO;
goto cancel;
}
--
1.8.3.1
^ permalink raw reply related
* RE: [PATCH] check the power management bit in MAC Header on Action Frame.
From: 기상원 (SW Ki) @ 2013-09-13 3:22 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, C1-G2-6 Team
RGVhciBKb2hhbm5lcywNCg0KSSBoYXZlIGZvdW5kIG9uZSBwcm9ibGVtIGluIHRoZSBtYWM4MDIx
MSByeCByb3V0aW5lIGR1cmluZyBtYWtpbmcgdGhlIFdpRmktRGlyZWN0IENlcnRpZmljYXRpb24u
IA0KVGhlIFN0ZXAgNCBvZiA2LjEuOSBmb3IgIkdPVVQgaGFuZGxpbmcgUDJQIFByZXNlbnNjZSBS
ZXF1ZXN0IiBtdXN0IGhhdmUgZm9sbG93aW5nIHJlc3VsdC4NCsKgICJTTihTbmlmZmVyKTogUDJQ
IFByZXNlbnNjZSBSZXNwb25zZSBuZWVkcyB0byBjb21iYWNrIHdpdGhpbiAxMDBtcy4gSWYgbm8g
cmVzcG9uc2UgaXMgcmVjZWl2ZWQgd2l0aGluIHRoaXMgdGhpZSwgRkFJTCB0ZXN0LiINCg0KVW5m
b3J0dW5hdGVseSwgVGhlIEdPVVQgaGFzIFByZXNlbnNjZSBSZXNwb25zZSBwYWNrZXQgdHJhbnNt
aXNzaW9uIGFmdGVyIDIwMG1zLiBUaGVuIE91ciBEVVQgZG8gbm90IHBhc3MgdGhpcyB0ZXN0LiAu
DQoNClNvLCBJIGhhdmUgb2JzZXJ2ZWQgcGFja2V0cyB0aHJvdWdoIHNuaWZmZXIgZm9yIHRoaXMg
dGVzdCBzdGVwLg0KSSBzYXcgdGhlIE5VTEwgUGFja2V0IHRoYXQgaW5jbHVkZSB0aGUgcG93ZXIg
bWFuYWdlbWVudCBiaXQgc2V0IHRvICcxJyBiZWZvcmUgc2VuZGluZyB0aGUgUHJlc2Vuc2NlIFJl
cXVlc3QgdGhhdCBpbmNsdWRlIFBNIGJpdCBzZXQgdG8gJzAnLg0KKFRoZSB0aW1lIGludGVydmFs
IGJldHdlZW4gdHdvIHBhY2tldHMgaXMgYWJvdXQgMm1zLikNCg0KDQpkaWZmIC11ck4gb3JpZy9t
YWM4MDIxMS9yeC5jIG5ldy9tYWM4MDIxMS9yeC5jDQotLS0gb3JpZy9tYWM4MDIxMS9yeC5jwqAg
MjAxMy0wOS0xMyAxMjoxNzo1OS4wMDAwMDAwMDAgKzA5MDANCisrKyBuZXcvbWFjODAyMTEvcngu
Y8KgwqAgMjAxMy0wOS0xMyAxMjoxNzowMi4wMDAwMDAwMDAgKzA5MDANCkBAIC0xMzI1LDcgKzEz
MjUsNyBAQA0KwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg
ICogZG96ZS0+d2FrZSB0cmFuc2l0aW9uIGZvciB0aGUgcHJvYmUgcmVxdWVzdCwNCsKgwqDCoMKg
wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAqIGFuZCB0aGF0IGlzIGNs
ZWFybHkgdW5kZXNpcmFibGUuDQrCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC
oMKgwqDCoMKgwqAgKi8NCi3CoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg
wqDCoCBpZiAoaWVlZTgwMjExX2lzX2RhdGEoaGRyLT5mcmFtZV9jb250cm9sKSAmJg0KK8KgwqDC
oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGlmICgoaWVlZTgwMjExX2lz
X2RhdGEoaGRyLT5mcmFtZV9jb250cm9sKSB8fCBpZWVlODAyMTFfaXNfYWN0aW9uKGhkci0+ZnJh
bWVfY29udHJvbCkpICYmDQrCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg
wqDCoMKgwqDCoMKgwqAgIWllZWU4MDIxMV9oYXNfcG0oaGRyLT5mcmFtZV9jb250cm9sKSkNCsKg
wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC
oMKgIGFwX3N0YV9wc19lbmQoc3RhKTsNCsKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCB9
IGVsc2Ugew0KDQoNCg0KSSBjYW4gc2VlIFByZXNlbnNjZSBSZXNwb25zZSB3aXRoaW4gMzBtcyBh
ZnRlciBhcHBseWluZyB0aGUgYmVsb3cgcGF0Y2guDQooVGhhdCBpcyBzdWNjZXNzIHJlc3VsdCBm
b3IgU3RlcCA0IG9mIDYuMS45KQ0KDQpDb3VsZCB5b3UgcmV2aWV3IG15IHBhdGNoIGNvZGUuDQpC
ZXN0IFJlZ2FyZHMsIFNhbmd3b24sIGtpDQo=
^ permalink raw reply
* start_next_roc splat in 3.11.0+
From: Ben Greear @ 2013-09-12 23:08 UTC (permalink / raw)
To: linux-wireless@vger.kernel.org
Was bringing up 128 stations configured for HotSpot 2.0 (wpa2, 802.1x, etc)
on a relatively slow machine.
I doubt it has much to do with how they are configured however.
The warning that hit is here:
roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
list);
if (WARN_ON_ONCE(roc->started))
return;
This is running my normal set of patches.
[ 133.530413] ------------[ cut here ]------------
[ 133.541409] WARNING: CPU: 1 PID: 7246 at /home/greearb/git/linux-3.11.dev.y/net/mac80211/offchannel.c:269 ieee80211_start_next_roc+0x1f1/0x210 [mac80211]()
[ 133.565902] Modules linked in: nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack 8021q garp stp mrp llc fuse macvlan wanlink(O) pktgen
iTCO_wdt gpio_ich iTCO_vendor_support arc4 pcspkr serio_raw i2c_i801 snd_hda_codec_realtek lpc_ich joydev ath9k_htc ath9k snd_hda_intel ath9k_common
snd_hda_codec snd_hwdep ath9k_hw ath mac80211 snd_seq snd_seq_device cfg80211 snd_pcm rfkill r8169 mii snd_page_alloc snd_timer snd soundcore uinput i915 video
i2c_algo_bit drm_kms_helper drm i2c_core [last unloaded: iptable_nat]
[ 133.643933] CPU: 1 PID: 7246 Comm: ip Tainted: G C O 3.11.0+ #21
[ 133.659832] Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M., BIOS 080015 05/31/2010
[ 133.679989] 0000010d efa6b964 c09c877c f849d0e4 efa6b994 c0459804 c0b65c08 00000001
[ 133.694895] 00001c4e f849d0e4 0000010d f844a711 f844a711 f7774360 f7774360 00000001
[ 133.708929] efa6b9a4 c0459842 00000009 00000000 efa6b9dc f844a711 efd14c30 f7774e78
[ 133.723050] Call Trace:
[ 133.731352] [<c09c877c>] dump_stack+0x4c/0x78
[ 133.741687] [<c0459804>] warn_slowpath_common+0x84/0xa0
[ 133.752888] [<f844a711>] ? ieee80211_start_next_roc+0x1f1/0x210 [mac80211]
[ 133.765706] [<f844a711>] ? ieee80211_start_next_roc+0x1f1/0x210 [mac80211]
[ 133.778334] [<c0459842>] warn_slowpath_null+0x22/0x30
[ 133.789153] [<f844a711>] ieee80211_start_next_roc+0x1f1/0x210 [mac80211]
[ 133.801612] [<f846879e>] ? ieee80211_queue_work+0x2e/0x40 [mac80211]
[ 133.813715] [<f848759d>] ? ieee80211_mesh_notify_scan_completed+0x7d/0x90 [mac80211]
[ 133.827250] [<f844983a>] __ieee80211_scan_completed+0xca/0x1f0 [mac80211]
[ 133.839946] [<f8449a49>] ieee80211_scan_cancel+0xe9/0x190 [mac80211]
[ 133.852084] [<c0459fa8>] ? put_online_cpus+0x48/0x70
[ 133.862866] [<f8453547>] ieee80211_do_stop+0x647/0x700 [mac80211]
[ 133.874749] [<c09009d6>] ? dev_deactivate_many+0x1e6/0x210
[ 133.885858] [<f8453667>] ieee80211_stop+0x17/0x20 [mac80211]
[ 133.897063] [<c08e3049>] __dev_close_many+0x69/0xb0
[ 133.907875] [<c08fbe5e>] ? netpoll_rx_disable+0x3e/0x50
[ 133.918588] [<c08e30c6>] __dev_close+0x36/0x70
[ 133.928541] [<c08e2302>] __dev_change_flags+0x82/0x150
[ 133.939080] [<c0916554>] ? ip_local_deliver+0x44/0x90
[ 133.949514] [<c08e4033>] dev_change_flags+0x23/0x60
[ 133.959742] [<c08f17a4>] do_setlink+0x224/0x7a0
[ 133.969666] [<c06be142>] ? nla_parse+0x22/0xd0
[ 133.979333] [<c08f4b72>] rtnl_newlink+0x532/0x5b0
[ 133.989164] [<c06444fc>] ? security_capable+0x1c/0x30
[ 133.999259] [<c0461e4a>] ? ns_capable+0x2a/0x60
[ 134.008797] [<c08f2129>] rtnetlink_rcv_msg+0x179/0x1f0
[ 134.019120] [<c05596bd>] ? __kmalloc_track_caller+0x2d/0x170
[ 134.029897] [<c0515e66>] ? find_get_page+0x66/0xb0
[ 134.040175] [<c08d877b>] ? __alloc_skb+0x6b/0x180
[ 134.050340] [<c08f1fb0>] ? rtnetlink_rcv+0x30/0x30
[ 134.060039] [<c090b016>] netlink_rcv_skb+0x86/0xb0
[ 134.069626] [<c08f1f9c>] rtnetlink_rcv+0x1c/0x30
[ 134.078854] [<c090ad86>] netlink_unicast+0xe6/0x140
[ 134.088397] [<c090ba72>] netlink_sendmsg+0x242/0x620
[ 134.097907] [<c0452203>] ? __kunmap_atomic+0x83/0xa0
[ 134.107349] [<c051c780>] ? get_page_from_freelist+0x250/0x500
[ 134.117435] [<c08d147a>] sock_sendmsg+0xaa/0xe0
[ 134.126226] [<c08cf608>] ? copy_from_user+0x8/0x10
[ 134.135068] [<c08dba2b>] ? verify_iovec+0x5b/0xb0
[ 134.143761] [<c08d2285>] ___sys_sendmsg+0x2c5/0x2e0
[ 134.152498] [<c052244d>] ? lru_cache_add+0xd/0x10
[ 134.160935] [<c053adc3>] ? handle_pte_fault+0x493/0xae0
[ 134.169849] [<c08d7e30>] ? skb_dequeue+0x50/0x70
[ 134.178135] [<c053b601>] ? handle_mm_fault+0x1f1/0x300
[ 134.186733] [<c08d241e>] __sys_sendmsg+0x3e/0x70
[ 134.194841] [<c08d2466>] SyS_sendmsg+0x16/0x20
[ 134.202652] [<c08d27af>] SyS_socketcall+0x11f/0x2e0
[ 134.210877] [<c0566f7d>] ? ____fput+0xd/0x10
[ 134.218528] [<c09d364d>] sysenter_do_call+0x12/0x28
[ 134.226767] ---[ end trace 2b5f2f9c64702e82 ]---
[ 134.251401] ath: wiphy0: Failed to stop TX DMA, queues=0x005!
[ 134.280969] ath: wiphy0: Failed to stop TX DMA, queues=0x004!
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: RTL8192CU continually reconnecting
From: Timothy Rundle @ 2013-09-12 23:02 UTC (permalink / raw)
Cc: linux-wireless
In-Reply-To: <5230CDF1.1040905@lwfinger.net>
I finally got some free time to go through all the patches. My results
were similar to Mark's, but I do not get the watchdog messages, though
I am pretty sure watchdog is disabled on my PC. I did even try
installing openSUSE 12.3, but did not have any success. It didn't
even find my wireless network. I manually configured the network via
network-manager, but still no luck.
Let me know if you need anything else from me.
On Wed, Sep 11, 2013 at 4:09 PM, Larry Finger <Larry.Finger@lwfinger.net> wrote:
> On 09/10/2013 03:04 PM, Mark Cave-Ayland wrote:
>
>> Interesting. Perhaps there is something different in the initial
>> programming of
>> the radio that causes it to crash on my particular hardware revision? As
>> before,
>> please let me know if there is anything else you require.
>
>
> From the log data, you have the same revision as I do.
>
> I am now running a kernel built with your configuration. I needed to make a
> couple of changes as it did not have one of the modules my disk system
> needs, and nouveau caused kernel panics, but we are now operational. Outside
> of the whole system being slow due to only one 2.0 GHz CPU, the wireless
> connection seems to be stable. At least, there have been no disconnects in
> the first half hour.
>
> Larry
>
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox