* Re: [PATCH 4/7] ath6kl: Add new functions to handle wow suspend/resume operations
From: Raja Mani @ 2011-10-31 9:53 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless
In-Reply-To: <4EAAA08F.5070905@qca.qualcomm.com>
On Friday 28 October 2011 06:01 PM, Kalle Valo wrote:
> On 10/25/2011 01:37 PM, rmani@qca.qualcomm.com wrote:
>> From: Raja Mani<rmani@qca.qualcomm.com>
>>
>> Signed-off-by: Raja Mani<rmani@qca.qualcomm.com>
>
> Empty commit log.
>
>> +int ath6kl_pm_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
>> +{
>> + struct wmi_set_wow_mode_cmd wakeup_filter_cmd;
>> + struct wmi_add_wow_pattern_cmd add_pattern_cmd;
>> + struct wmi_del_wow_pattern_cmd del_pattern_cmd;
>> + struct wmi_set_host_sleep_mode_cmd hsleep_cmd;
>> + int i, ret, pos, left;
>> + u8 mask[WOW_PATTERN_SIZE];
>> +
>> + if (WARN_ON(!wow))
>> + return -EINVAL;
>
> Unnecessary null check, wow is non-zero here.
>
>> + for (pos = 0; pos< wow->patterns[i].pattern_len;
>> + pos++) {
>> + if (wow->patterns[i].mask[pos / 8]& (0x1<< (pos % 8)))
>> + mask[pos] = 0xFF;
>
> This loop needs a comment.
>
>> + if (ar->tx_pending[ar->ctrl_ep]) {
>> + left = wait_event_interruptible_timeout(ar->event_wq,
>> + ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT);
>> + if (left == 0) {
>> + ret = -ETIMEDOUT;
>> + goto wow_setup_failed;
>> + } else if (left< 0) {
>> + ret = left;
>> + goto wow_setup_failed;
>
> A warning message for both of these error case would be nice.
>
>> +#define WOW_HOST_REQ_DELAY 500 /* 500 ms */
>
> No point of duplicating the value, "/* ms */" is enough.
>
> Kalle
Will fix all your above comments in V2..
^ permalink raw reply
* Re: [PATCH 0/7] ath6kl: Add WOW support
From: Raja Mani @ 2011-10-31 9:55 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless
In-Reply-To: <4EAA98EF.9070004@qca.qualcomm.com>
On Friday 28 October 2011 05:28 PM, Kalle Valo wrote:
> On 10/25/2011 01:37 PM, rmani@qca.qualcomm.com wrote:
>
>> Using these patch sets, WOW patterns can be controlled
>> and configured via iw command. Please refer iw help menu for more details.
>>
>> There are some limitation in the recent "iw" command such as it doesn't
>> take the pattern offset where to start pattern matching in the received packets.
>> Such a enhancement will be done later..
>>
>> These patch sets are re-based on master branch, available in git://github.com/kvalo/ath6kl.git
>
> These patches conflict with multi vif so you need to rebase your
> patches. I also saw few sparse warnings:
Thanks for your review, I'll fix below sparse warnings and rebase &
submit V2.
>
> drivers/net/wireless/ath/ath6kl/cfg80211.c:1512:42: warning: incorrect
> type in assignment (different base types)
> drivers/net/wireless/ath/ath6kl/cfg80211.c:1512:42: expected
> restricted __le16 [addressable] [assigned] [usertype] host_req_delay
> drivers/net/wireless/ath/ath6kl/cfg80211.c:1512:42: got restricted
> __le32 [usertype]<noident>
> drivers/net/wireless/ath/ath6kl/cfg80211.c:1485:5: warning: symbol
> 'ath6kl_pm_wow_suspend' was not declared. Should it be static?
> drivers/net/wireless/ath/ath6kl/cfg80211.c:1586:5: warning: symbol
> 'ath6kl_pm_wow_resume' was not declared. Should it be static?
>
> Kalle
^ permalink raw reply
* Re: [PATCH 5/7] ath6kl: Invoke wow suspend/resume calls during PM operations
From: Raja Mani @ 2011-10-31 9:54 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless
In-Reply-To: <4EAAAC61.405@qca.qualcomm.com>
On Friday 28 October 2011 06:51 PM, Kalle Valo wrote:
> On 10/25/2011 01:37 PM, rmani@qca.qualcomm.com wrote:
>
>> + if (wow&& ath6kl_cfg80211_ready(ar)&&
>> + test_bit(CONNECTED,&ar->flag)&&
>> + ath6kl_hif_keep_pwr_caps(ar)) {
>> +
>> + /* Flush all non control pkts in Tx path */
>> + ath6kl_tx_data_cleanup(ar);
>> +
>> + ret = ath6kl_pm_wow_suspend(ar, wow);
>> + if (ret)
>> + return ret;
>> + }
>
> Forgot to mention: don't you also need to check for MMC_PM_WAKE_SDIO_IRQ
> and also set it with sdio_set_host_pm_flags()?
I tested it in x86 machine. Wow suspend/resume works even without
setting MMC_PM_WAKE_SDIO_IRQ. Should i really handle it ?
>
> Kalle
^ permalink raw reply
* Re: [PATCH 5/7] ath6kl: Invoke wow suspend/resume calls during PM operations
From: Raja Mani @ 2011-10-31 9:54 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless
In-Reply-To: <4EAAAAF6.3090906@qca.qualcomm.com>
On Friday 28 October 2011 06:45 PM, Kalle Valo wrote:
> On 10/25/2011 01:37 PM, rmani@qca.qualcomm.com wrote:
>> From: Raja Mani<rmani@qca.qualcomm.com>
>>
>> Link ath6kl's wow suspend/resume functions with the callback functions
>> registered with the CFG layer for suspend and resume operation.
>
> [..]
>
>> --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
>> +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
>> @@ -1606,6 +1606,19 @@ static int ar6k_cfg80211_suspend(struct wiphy *wiphy,
>> struct cfg80211_wowlan *wow)
>> {
>> struct ath6kl *ar = wiphy_priv(wiphy);
>> + int ret;
>> +
>> + if (wow&& ath6kl_cfg80211_ready(ar)&&
>> + test_bit(CONNECTED,&ar->flag)&&
>> + ath6kl_hif_keep_pwr_caps(ar)) {
>> +
>> + /* Flush all non control pkts in Tx path */
>> + ath6kl_tx_data_cleanup(ar);
>> +
>> + ret = ath6kl_pm_wow_suspend(ar, wow);
>> + if (ret)
>> + return ret;
>> + }
>
> This is now confusing. Some of the suspend logic is now in sdio.c and
> some here. It's better to have everything in one place, that is in
> sdio.c. We just need to add an interface so that sdio.c can request the
> correct suspend mode.
Do you want me to keep ath6kl_pm_wow_suspend() implementation in
cfg80211.c file and move only above code to ath6kl_sdio_suspend() ?
>
> Kalle
^ permalink raw reply
* Re: [PATCH 2/7] ath6kl: Add wmi functions to configure wow mode and host sleep mode
From: Raja Mani @ 2011-10-31 9:53 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless
In-Reply-To: <4EAA9DDC.5090909@qca.qualcomm.com>
On Friday 28 October 2011 05:49 PM, Kalle Valo wrote:
> On 10/25/2011 01:37 PM, rmani@qca.qualcomm.com wrote:
>> From: Raja Mani<rmani@qca.qualcomm.com>
>>
>> Signed-off-by: Raja Mani<rmani@qca.qualcomm.com>
>
> Empty commit log.
I'll add commit log here..
>
>> +static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
>> +{
>> + u16 active_tsids;
>> + u8 stream_exist;
>> + int i;
>> +
>> + /*
>> + * Relinquish credits from all implicitly created pstreams
>> + * since when we go to sleep. If user created explicit
>> + * thinstreams exists with in a fatpipe leave them intact
>> + * for the user to delete.
>> + */
>> + spin_lock_bh(&wmi->lock);
>> + stream_exist = wmi->fat_pipe_exist;
>> + spin_unlock_bh(&wmi->lock);
>> +
>> + for (i = 0; i< WMM_NUM_AC; i++) {
>> + if (stream_exist& (1<< i)) {
>> +
>> + spin_lock_bh(&wmi->lock);
>> + active_tsids = wmi->stream_exist_for_ac[i];
>> + spin_unlock_bh(&wmi->lock);
>> +
>> + /*
>> + * If there are no user created thin streams
>> + * delete the fatpipe
>> + */
>> + if (!active_tsids) {
>> + stream_exist&= ~(1<< i);
>> + /*
>> + * Indicate inactivity to driver layer for
>> + * this fatpipe (pstream)
>> + */
>> + ath6kl_indicate_tx_activity(wmi->parent_dev,
>> + i, false);
>> + }
>> + }
>> + }
>> +
>> + spin_lock_bh(&wmi->lock);
>> + wmi->fat_pipe_exist = stream_exist;
>> + spin_unlock_bh(&wmi->lock);
>
> The locking here doesn't really make sense. For example, any changes to
> wmi->fat_pipe_exist during the for loop will be overwritten. Also lock
> handling with wmi->stream_exist_for_ac[i] looks fishy.
Is it fine just removal of both locking (For "active_tsids =
wmi->stream_exist_for_ac[i]" and "wmi->fat_pipe_exist = stream_exist") ?
I am sure about the impact..Could you please give some point how above
locking can be improved ?
>
>> +int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi,
>> + struct wmi_set_host_sleep_mode_cmd *host_mode)
>
> Don't use the struct as a parameter, you could instead provide an enum
> like this:
>
> enum ath6kl_host_mode {
> ATH6KL_HOST_MODE_AWAKE,
> ATH6KL_HOST_MODE_ASLEEP,
> };
>
Okay.
>> +{
>> + struct sk_buff *skb;
>> + struct wmi_set_host_sleep_mode_cmd *cmd;
>> + int ret;
>> +
>> + if (host_mode->awake == host_mode->asleep)
>> + return -EINVAL;
>
> ...and then you can remove this test.
Fine.
>
>> +int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi,
>> + struct wmi_set_wow_mode_cmd *wow_mode)
>
> I'm sure you can guess what I'm about to say here ;)
:) Got it..
>
> Kalle
^ permalink raw reply
* Re: [PATCH 1/7] ath6kl: Add wmi functions to add/delete wow patterns
From: Raja Mani @ 2011-10-31 9:52 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless
In-Reply-To: <4EAA9BE2.7050808@qca.qualcomm.com>
On Friday 28 October 2011 05:41 PM, Kalle Valo wrote:
> On 10/25/2011 01:37 PM, rmani@qca.qualcomm.com wrote:
>> From: Raja Mani<rmani@qca.qualcomm.com>
>>
>> Signed-off-by: Raja Mani<rmani@qca.qualcomm.com>
>
> Try to avoid empty commit logs. You could just say that these commands
> will be used by the following patch if nothing else.
>
>> +int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi,
>> + struct wmi_add_wow_pattern_cmd *add_wow_cmd,
>> + u8 *pattern, u8 *mask)
>> +{
>
> Don't use a struct as the parameter, instead add individual parameters.
> So something like this:
>
> int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi,
> u8 id, u8 size, 8 offset,
> u8 *pattern, u8 *mask)
>
> This is easier for the caller and you get to handle the endian in the
> callee which simplifies the code.
Agree.. I'll take care in V2.
>
>> + size = sizeof(*cmd) +
>> + ((2 * add_wow_cmd->filter_size) * sizeof(u8));
>
> This can fit into line. And sizeof(u8) really doesn't make any sense.
>
> And is this correct? The struct is defined like this:
>
> +struct wmi_add_wow_pattern_cmd {
> + u8 filter_list_id;
> + u8 filter_size;
> + u8 filter_offset;
> + u8 filter[1];
> +} __packed;
>
> So there's one extra byte for the filter and above you include also that
> byte. But if the sctruct is defined like this the extra byte is not
> included:
>
> +struct wmi_add_wow_pattern_cmd {
> + u8 filter_list_id;
> + u8 filter_size;
> + u8 filter_offset;
> + u8 filter[0];
> +} __packed;
>
Good catch.. I'll correct it.
>> +int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi,
>> + struct wmi_del_wow_pattern_cmd *del_wow_cmd)
>
> Same here as earlier, don't use the struct as a parameter.
Okay..
>
> Kalle
^ permalink raw reply
* Re: [PATCH] wl12xx: set scan probe requests rate according to the no_cck flag
From: Luciano Coelho @ 2011-10-31 9:36 UTC (permalink / raw)
To: guy; +Cc: linux-wireless, eliad
In-Reply-To: <CAB3XZEdk2pxH4k4tYXn44Sdb8STdXEh7VVsE85__e=M2Fk9s7A@mail.gmail.com>
On Sun, 2011-10-16 at 12:58 +0200, Eliad Peller wrote:
> hi Guy,
>
> On Sat, Oct 15, 2011 at 10:23 PM, Guy Eilam <guy@wizery.com> wrote:
> > Set the TX rate of probe requests during scanning according to the
> > no_cck flag in the scan request struct.
> >
> > Signed-off-by: Guy Eilam <guy@wizery.com>
> > ---
> [...]
>
> > @@ -243,7 +242,12 @@ void wl1271_scan_stm(struct wl1271 *wl)
> >
> > case WL1271_SCAN_STATE_2GHZ_ACTIVE:
> > band = IEEE80211_BAND_2GHZ;
> > - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
> > + if (wl->scan.req->no_cck)
> > + rate = wl1271_tx_min_rate_get(wl,
> > + CONF_TX_RATE_MASK_BASIC_P2P);
> > + else
> > + rate = wl1271_tx_min_rate_get(wl,
> > + CONF_TX_RATE_MASK_BASIC);
>
> on a second thought, this seems a bit wrong.
> i think we should consider the configured bitrate_masks when scanning.
> maybe just mask-out the cck rates?
Any follow up on this?
--
Cheers,
Luca.
^ permalink raw reply
* Re: [PATCH 2/4] mac80211: QoS multicast frames have No Ack policy
From: Christian Lamparter @ 2011-10-31 9:16 UTC (permalink / raw)
To: Thomas Pedersen; +Cc: linux-wireless, devel, johannes, linville
In-Reply-To: <CAG6hwVPNfqriCij5p3Lia2+=ob0AwQjPQFXUssumvBMvu51qTg@mail.gmail.com>
On Monday, October 31, 2011 08:03:12 AM Thomas Pedersen wrote:
> On Sat, Oct 29, 2011 at 2:40 AM, Christian Lamparter <chunkeey@googlemail.com> wrote:
> > ack_policy = *ieee80211_get_qos_ctl(hdr) & ~IEEE80211_QOS_CTL_ACK_POLICY_MASK;
>
> Good idea. Will fix and resubmit.
hmpf, make that: (stupid c&p typo :) )
ack_policy = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_ACK_POLICY_MASK;
Regards,
Chr
^ permalink raw reply
* [PATCH v2 4/4] mac80211: Populate QoS header on mesh frames sent to gates.
From: Thomas Pedersen @ 2011-10-31 7:12 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, johannes, linville
In-Reply-To: <1320045161-16144-1-git-send-email-thomas@cozybit.com>
From: Javier Cardona <javier@cozybit.com>
Also set correct skb queue mapping once next hop is known, and set
txinfo jiffies when forwarding.
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh_hwmp.c | 5 ++++-
net/mac80211/mesh_pathtbl.c | 5 +++++
net/mac80211/rx.c | 8 +++++---
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index b7d9dfd..d46109b 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -1028,8 +1028,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
PREQ_Q_F_START | PREQ_Q_F_REFRESH);
}
next_hop = rcu_dereference(mpath->next_hop);
- if (next_hop)
+ if (next_hop) {
memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
+ skb_set_queue_mapping(skb,
+ ieee80211_select_queue(sdata, skb));
+ }
else
err = -ENOENT;
} else {
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 332b5ff1..9d2f55f 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -270,6 +270,11 @@ static void prepare_for_gate(struct sk_buff *skb, char *dst_addr,
memcpy(hdr->addr1, next_hop, ETH_ALEN);
rcu_read_unlock();
memcpy(hdr->addr3, dst_addr, ETH_ALEN);
+
+ /* once next hop is set we can set qos header */
+ skb_set_queue_mapping(skb,
+ ieee80211_select_queue(gate_mpath->sdata, skb));
+ ieee80211_set_qos_hdr(gate_mpath->sdata, skb);
}
/**
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 0995685..00b3db7 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1964,12 +1964,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
memset(info, 0, sizeof(*info));
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
info->control.vif = &rx->sdata->vif;
+ info->control.jiffies = jiffies;
if (is_multicast_ether_addr(fwd_hdr->addr1)) {
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
fwded_mcast);
- skb_set_queue_mapping(fwd_skb,
- ieee80211_select_queue(sdata, fwd_skb));
- ieee80211_set_qos_hdr(sdata, fwd_skb);
} else {
int err;
/*
@@ -1990,6 +1988,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
}
IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
fwded_frames);
+
+ /* next hop is now known, update the queue mapping */
+ skb_set_queue_mapping(fwd_skb,
+ ieee80211_select_queue(sdata, fwd_skb));
ieee80211_add_pending_skb(local, fwd_skb);
}
}
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2 3/4] mac80211: check if frame is really part of this BA
From: Thomas Pedersen @ 2011-10-31 7:12 UTC (permalink / raw)
To: linux-wireless; +Cc: Thomas Pedersen, johannes, linville
In-Reply-To: <1320045161-16144-1-git-send-email-thomas@cozybit.com>
There was an an implicit assumption that any QoS data frame received
from a STA/TID with an active BA session was sent to this vif as part of
a BA. This is not true if IFF_PROMISC is enabled and the frame was
destined for a different peer, for example. Don't treat these frames as
part of a BA from the sending STA.
Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
---
net/mac80211/rx.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b9d3236..0995685 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -777,6 +777,10 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
(ack_policy == IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)))
goto dont_reorder;
+ /* not actually part of this BA session */
+ if (compare_ether_addr(hdr->addr1, rx->sdata->vif.addr) != 0)
+ goto dont_reorder;
+
/* new, potentially un-ordered, ampdu frame - process it */
/* reset session timer */
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2 2/4] mac80211: QoS multicast frames have No Ack policy
From: Thomas Pedersen @ 2011-10-31 7:12 UTC (permalink / raw)
To: linux-wireless; +Cc: Thomas Pedersen, johannes, linville
In-Reply-To: <1320045161-16144-1-git-send-email-thomas@cozybit.com>
Previously QoS multicast frames had the Normal Acknowledgment QoS
control bits set. This would cause broadcast frames to be discarded by
peers with which we have a BA session, since their sequence number would
fall outside the allowed range. Set No Ack QoS control bits on multicast
QoS frames and filter these in de-aggregation code.
Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
---
v2: Use proper QoS Ack Policy control field mask (Christian)
include/linux/ieee80211.h | 1 +
net/mac80211/rx.c | 9 ++++++++-
net/mac80211/wme.c | 3 ++-
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 48363c3..bc61e69 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -128,6 +128,7 @@
#define IEEE80211_QOS_CTL_ACK_POLICY_NOACK 0x0020
#define IEEE80211_QOS_CTL_ACK_POLICY_NO_EXPL 0x0040
#define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060
+#define IEEE80211_QOS_CTL_ACK_POLICY_MASK 0x0060
/* A-MSDU 802.11n */
#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080
/* Mesh Control 802.11s */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b867bd5..b9d3236 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -747,7 +747,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
struct sta_info *sta = rx->sta;
struct tid_ampdu_rx *tid_agg_rx;
u16 sc;
- int tid;
+ u8 tid, ack_policy;
if (!ieee80211_is_data_qos(hdr->frame_control))
goto dont_reorder;
@@ -760,6 +760,8 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
if (!sta)
goto dont_reorder;
+ ack_policy = *ieee80211_get_qos_ctl(hdr) &
+ IEEE80211_QOS_CTL_ACK_POLICY_MASK;
tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
@@ -770,6 +772,11 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
goto dont_reorder;
+ /* not part of a BA session */
+ if (!((ack_policy == IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK) ||
+ (ack_policy == IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)))
+ goto dont_reorder;
+
/* new, potentially un-ordered, ampdu frame - process it */
/* reset session timer */
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index fd52e69..a440a4a 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -147,7 +147,8 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
- if (unlikely(sdata->local->wifi_wme_noack_test))
+ if (unlikely(sdata->local->wifi_wme_noack_test) ||
+ is_multicast_ether_addr(hdr->addr1))
ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
/* qos header is 2 bytes */
*p++ = ack_policy | tid;
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2 1/4] mac80211: Avoid filling up mesh preq queue with redundant requests
From: Thomas Pedersen @ 2011-10-31 7:12 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, johannes, linville
From: Javier Cardona <javier@cozybit.com>
Don't accept redundant PREQs for a given destination. This fixes a
problem under high load:
kernel: [20386.250913] mesh_queue_preq: 235 callbacks suppressed
kernel: [20386.253335] Mesh HWMP (mesh0): PREQ node queue full
kernel: [20386.253352] Mesh HWMP (mesh0): PREQ node queue full
(...)
The 802.11s protocol has a provision to limit the rate of path requests
(PREQs) are transmitted (dot11MeshHWMPpreqMinInterval) but there was no
limit on the rate at which PREQs were being queued up. There is a valid
reason for queuing PREQs: this way we can even out PREQ bursts. But
queueing multiple PREQs for the same destination is useless.
Reported-by: Pedro Larbig <pedro.larbig@carhs.de>
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh.h | 3 +++
net/mac80211/mesh_hwmp.c | 15 +++++++++++++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 8c00e2d..b3745e8 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -31,6 +31,8 @@
* @MESH_PATH_FIXED: the mesh path has been manually set and should not be
* modified
* @MESH_PATH_RESOLVED: the mesh path can has been resolved
+ * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination
+ * already queued up, waiting for the discovery process to start.
*
* MESH_PATH_RESOLVED is used by the mesh path timer to
* decide when to stop or cancel the mesh path discovery.
@@ -41,6 +43,7 @@ enum mesh_path_flags {
MESH_PATH_SN_VALID = BIT(2),
MESH_PATH_FIXED = BIT(3),
MESH_PATH_RESOLVED = BIT(4),
+ MESH_PATH_REQ_QUEUED = BIT(5),
};
/**
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 9a1f8bb..b7d9dfd 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -867,9 +867,19 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
return;
}
+ spin_lock_bh(&mpath->state_lock);
+ if (mpath->flags & MESH_PATH_REQ_QUEUED) {
+ spin_unlock_bh(&mpath->state_lock);
+ spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
+ return;
+ }
+
memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
preq_node->flags = flags;
+ mpath->flags |= MESH_PATH_REQ_QUEUED;
+ spin_unlock_bh(&mpath->state_lock);
+
list_add_tail(&preq_node->list, &ifmsh->preq_queue.list);
++ifmsh->preq_queue_len;
spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
@@ -921,6 +931,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
goto enddiscovery;
spin_lock_bh(&mpath->state_lock);
+ mpath->flags &= ~MESH_PATH_REQ_QUEUED;
if (preq_node->flags & PREQ_Q_F_START) {
if (mpath->flags & MESH_PATH_RESOLVING) {
spin_unlock_bh(&mpath->state_lock);
@@ -1028,8 +1039,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
mesh_queue_preq(mpath, PREQ_Q_F_START);
}
- if (skb_queue_len(&mpath->frame_queue) >=
- MESH_FRAME_QUEUE_LEN)
+ if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN)
skb_to_free = skb_dequeue(&mpath->frame_queue);
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
@@ -1062,6 +1072,7 @@ void mesh_path_timer(unsigned long data)
++mpath->discovery_retries;
mpath->discovery_timeout *= 2;
spin_unlock_bh(&mpath->state_lock);
+ mpath->flags &= ~MESH_PATH_REQ_QUEUED;
mesh_queue_preq(mpath, 0);
} else {
mpath->flags = 0;
--
1.7.5.4
^ permalink raw reply related
* Re: [PATCH 2/4] mac80211: QoS multicast frames have No Ack policy
From: Thomas Pedersen @ 2011-10-31 7:03 UTC (permalink / raw)
To: Christian Lamparter; +Cc: linux-wireless, devel, johannes, linville
In-Reply-To: <201110291140.12311.chunkeey@googlemail.com>
On Sat, Oct 29, 2011 at 2:40 AM, Christian Lamparter
<chunkeey@googlemail.com> wrote:
> On Saturday 29 October 2011 07:05:30 Thomas Pedersen wrote:
>> Previously QoS multicast frames had the Normal Acknowledgment QoS
>> control bits set. This would cause broadcast frames to be discarded by
>> peers with which we have a BA session, since their sequence number would
>> fall outside the allowed range. Set No Ack QoS control bits on multicast
>> QoS frames and filter these in de-aggregation code.
>>
>> Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
>> ---
>> net/mac80211/rx.c | 8 +++++++-
>> net/mac80211/wme.c | 3 ++-
>> 2 files changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
>> index b867bd5..ee9e71b 100644
>> --- a/net/mac80211/rx.c
>> +++ b/net/mac80211/rx.c
>> @@ -747,7 +747,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
>> struct sta_info *sta = rx->sta;
>> struct tid_ampdu_rx *tid_agg_rx;
>> u16 sc;
>> - int tid;
>> + u8 tid, ack_policy;
>>
>> if (!ieee80211_is_data_qos(hdr->frame_control))
>> goto dont_reorder;
>> @@ -760,6 +760,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
>> if (!sta)
>> goto dont_reorder;
>>
>> + ack_policy = *ieee80211_get_qos_ctl(hdr) & ~IEEE80211_QOS_CTL_TID_MASK;
> uh, while it might be a bit far fetched, but ack_policy might now clash with
> frames that have set:
>
> IEEE80211_QOS_CTL_EOSP (0x10)
> IEEE80211_QOS_CTL_A_MSDU_PRESENT (0x80)
> IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT (0x100)
>
> so I think we would be better of with something like:
>
> (in include/linux/ieee80211.h)
> #define IEEE80211_QOS_CTL_ACK_POLICY_MASK 0x0060
>
> ack_policy = *ieee80211_get_qos_ctl(hdr) & ~IEEE80211_QOS_CTL_ACK_POLICY_MASK;
Good idea. Will fix and resubmit.
>
>> @@ -770,6 +771,11 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
>> if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
>> goto dont_reorder;
>>
>> + /* not part of a BA session */
>> + if (!((ack_policy == IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK) ||
>> + (ack_policy == IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)))
>> + goto dont_reorder;
>> +
Thanks,
Thomas
^ permalink raw reply
* Build Error Report
From: Masahiro Inoue @ 2011-10-31 1:35 UTC (permalink / raw)
To: linux-wireless
Hello,
The build error occurs by compat-wireless-2011-10-30.
My kernel is 2.6.27.
LD /home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros/atl1c/built-in.o
CC [M] /home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros/atl1c/atl1c_main.o
/home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros/atl1c/atl1c_main.c: In function 'atl1c_tx_map':
/home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros/atl1c/atl1c_main.c:2199: error: implicit declaration of function 'skb_frag_size'
/home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros/atl1c/atl1c_main.c: At top level:
/home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros/atl1c/atl1c_main.c:2926: warning: useless storage class specifier in empty declaration
/home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros/atl1c/atl1c_main.c:2926: warning: empty declaration
make[4]: *** [/home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros/atl1c/atl1c_main.o] Error 1
make[3]: *** [/home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros/atl1c] Error 2
make[2]: *** [/home/miyabi/test/compat-wireless/compat-wireless-2011-10-30/drivers/net/ethernet/atheros] Error 2
make[1]: *** [_module_/home/miyabi/test/compat-wireless/compat-wireless-2011-10-30] Error 2
make[1]: Leaving directory `/usr/src/kernels/2.6.27-71vl5-x86_64'
make: *** [modules] Error 2
^ permalink raw reply
* open802.11s on android
From: Nico Gerwien @ 2011-10-30 20:11 UTC (permalink / raw)
To: linux-wireless
Hi,
i didn't work with open802.11s yet. So i would like to know if it is
compilable on android systems?
Or is there already a precompiled package for android?
Greetings
Nicole
^ permalink raw reply
* open802.11s on android
From: Nico Gerwien @ 2011-10-30 20:10 UTC (permalink / raw)
To: linux-wireless
Hi,
i didn't work with open802.11s yet. So i would like to know if it is
compilable on android systems?
Or is there already a precompiled package for android?
Greetings
Nicole
^ permalink raw reply
* [PATCH 5/5] ath6kl: print seqno in htc debug logs
From: Kalle Valo @ 2011-10-30 19:16 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
In-Reply-To: <20111030190922.20466.299.stgit@localhost6.localdomain6>
Makes it easier to debug where frames are going.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/htc.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c
index 99220d4..f3b63ca 100644
--- a/drivers/net/wireless/ath/ath6kl/htc.c
+++ b/drivers/net/wireless/ath/ath6kl/htc.c
@@ -439,6 +439,9 @@ static void htc_tx_comp_handler(struct htc_target *target,
struct htc_endpoint *endpoint = &target->endpoint[packet->endpoint];
struct list_head container;
+ ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx complete seqno %d\n",
+ packet->info.tx.seqno);
+
htc_tx_comp_update(target, endpoint, packet);
INIT_LIST_HEAD(&container);
list_add_tail(&packet->list, &container);
@@ -501,8 +504,8 @@ static int ath6kl_htc_tx_issue(struct htc_target *target,
padded_len = CALC_TXRX_PADDED_LEN(target, send_len);
ath6kl_dbg(ATH6KL_DBG_HTC,
- "htc tx issue len %d padded_len %d mbox 0x%X %s\n",
- send_len, padded_len,
+ "htc tx issue len %d seqno %d padded_len %d mbox 0x%X %s\n",
+ send_len, packet->info.tx.seqno, padded_len,
target->dev->ar->mbox_info.htc_addr,
sync ? "sync" : "async");
@@ -705,8 +708,8 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target,
scat_req->len += len;
scat_req->scat_entries++;
ath6kl_dbg(ATH6KL_DBG_HTC,
- "htc tx adding (%d) pkt 0x%p len %d remaining %d\n",
- i, packet, len, rem_scat);
+ "htc tx adding (%d) pkt 0x%p seqno %d len %d remaining %d\n",
+ i, packet, packet->info.tx.seqno, len, rem_scat);
}
/* Roll back scatter setup in case of any failure */
^ permalink raw reply related
* [PATCH 4/5] ath6kl: print firmware crashes always
From: Kalle Valo @ 2011-10-30 19:16 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
In-Reply-To: <20111030190922.20466.299.stgit@localhost6.localdomain6>
Currently firmware crash dump is printed only if debug is enabled.
Change it so that the crash dump is always printed.
Also move the code from init.c to hif.c.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/core.h | 1
drivers/net/wireless/ath/ath6kl/hif.c | 69 ++++++++++++++++++++++++++++----
drivers/net/wireless/ath/ath6kl/init.c | 55 --------------------------
3 files changed, 61 insertions(+), 64 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 1ac0dd1..95aed7d 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -654,7 +654,6 @@ void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid);
void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
u8 win_sz);
void ath6kl_wakeup_event(void *dev);
-void ath6kl_target_failure(struct ath6kl *ar);
void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
bool wait_fot_compltn, bool cold_reset);
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c
index 309be98..e57da35 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.c
+++ b/drivers/net/wireless/ath/ath6kl/hif.c
@@ -59,26 +59,79 @@ int ath6kl_hif_rw_comp_handler(void *context, int status)
return 0;
}
+#define REG_DUMP_COUNT_AR6003 60
+#define REGISTER_DUMP_LEN_MAX 60
+
+static void ath6kl_hif_dump_fw_crash(struct ath6kl *ar)
+{
+ __le32 regdump_val[REGISTER_DUMP_LEN_MAX];
+ u32 i, address, regdump_addr = 0;
+ int ret;
+
+ if (ar->target_type != TARGET_TYPE_AR6003)
+ return;
+
+ /* the reg dump pointer is copied to the host interest area */
+ address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
+ address = TARG_VTOP(ar->target_type, address);
+
+ /* read RAM location through diagnostic window */
+ ret = ath6kl_diag_read32(ar, address, ®dump_addr);
+
+ if (ret || !regdump_addr) {
+ ath6kl_warn("failed to get ptr to register dump area: %d\n",
+ ret);
+ return;
+ }
+
+ ath6kl_dbg(ATH6KL_DBG_IRQ, "register dump data address 0x%x\n",
+ regdump_addr);
+ regdump_addr = TARG_VTOP(ar->target_type, regdump_addr);
+
+ /* fetch register dump data */
+ ret = ath6kl_diag_read(ar, regdump_addr, (u8 *)®dump_val[0],
+ REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
+ if (ret) {
+ ath6kl_warn("failed to get register dump: %d\n", ret);
+ return;
+ }
+
+ ath6kl_info("crash dump:\n");
+ ath6kl_info("hw 0x%x fw %s\n", ar->wiphy->hw_version,
+ ar->wiphy->fw_version);
+
+ BUILD_BUG_ON(REG_DUMP_COUNT_AR6003 % 4);
+
+ for (i = 0; i < REG_DUMP_COUNT_AR6003 / 4; i++) {
+ ath6kl_info("%d: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
+ 4 * i,
+ le32_to_cpu(regdump_val[i]),
+ le32_to_cpu(regdump_val[i + 1]),
+ le32_to_cpu(regdump_val[i + 2]),
+ le32_to_cpu(regdump_val[i + 3]));
+ }
+
+}
static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
{
u32 dummy;
- int status;
+ int ret;
- ath6kl_err("target debug interrupt\n");
-
- ath6kl_target_failure(dev->ar);
+ ath6kl_warn("firmware crashed\n");
/*
* read counter to clear the interrupt, the debug error interrupt is
* counter 0.
*/
- status = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS,
+ ret = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS,
(u8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC);
- if (status)
- WARN_ON(1);
+ if (ret)
+ ath6kl_warn("Failed to clear debug interrupt: %d\n", ret);
- return status;
+ ath6kl_hif_dump_fw_crash(dev->ar);
+
+ return ret;
}
/* mailbox recv message polling */
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index c197e4c..06e5cea 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -298,61 +298,6 @@ out:
return status;
}
-#define REG_DUMP_COUNT_AR6003 60
-#define REGISTER_DUMP_LEN_MAX 60
-
-static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
-{
- u32 address;
- u32 regdump_loc = 0;
- int status;
- u32 regdump_val[REGISTER_DUMP_LEN_MAX];
- u32 i;
-
- if (ar->target_type != TARGET_TYPE_AR6003)
- return;
-
- /* the reg dump pointer is copied to the host interest area */
- address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
- address = TARG_VTOP(ar->target_type, address);
-
- /* read RAM location through diagnostic window */
- status = ath6kl_diag_read32(ar, address, ®dump_loc);
-
- if (status || !regdump_loc) {
- ath6kl_err("failed to get ptr to register dump area\n");
- return;
- }
-
- ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n",
- regdump_loc);
- regdump_loc = TARG_VTOP(ar->target_type, regdump_loc);
-
- /* fetch register dump data */
- status = ath6kl_diag_read(ar, regdump_loc, (u8 *)®dump_val[0],
- REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
-
- if (status) {
- ath6kl_err("failed to get register dump\n");
- return;
- }
- ath6kl_dbg(ATH6KL_DBG_TRC, "Register Dump:\n");
-
- for (i = 0; i < REG_DUMP_COUNT_AR6003; i++)
- ath6kl_dbg(ATH6KL_DBG_TRC, " %d : 0x%8.8X\n",
- i, regdump_val[i]);
-
-}
-
-void ath6kl_target_failure(struct ath6kl *ar)
-{
- ath6kl_err("target asserted\n");
-
- /* try dumping target assertion information (if any) */
- ath6kl_dump_target_assert_info(ar);
-
-}
-
static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
{
int status = 0;
^ permalink raw reply related
* [PATCH 3/5] ath6kl: fix WLAN_ENABLE usage in ath6kl_close()
From: Kalle Valo @ 2011-10-30 19:16 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
In-Reply-To: <20111030190922.20466.299.stgit@localhost6.localdomain6>
If ath6kl_init_hw_stop() failed with an error WLAN_ENABLED would not
be cleared. Found during code review and just a theoretical issue.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/main.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 717ed22..def0b7f 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1147,7 +1147,6 @@ static int ath6kl_close(struct net_device *dev)
0, 0, 0, 0, 0, 0, 0, 0, 0))
return -EIO;
- clear_bit(WLAN_ENABLED, &vif->flags);
}
ath6kl_cfg80211_scan_complete_event(vif, -ECANCELED);
@@ -1157,6 +1156,8 @@ static int ath6kl_close(struct net_device *dev)
if (ret)
return ret;
+ clear_bit(WLAN_ENABLED, &vif->flags);
+
return 0;
}
^ permalink raw reply related
* [PATCH 2/5] ath6kl: power down hardware when interface is down
From: Kalle Valo @ 2011-10-30 19:16 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
In-Reply-To: <20111030190922.20466.299.stgit@localhost6.localdomain6>
The benefit from this is that user space can control hardware's power state
by putting interface up and down. This is handy if firmware gets to some
weird state.
The downside will be that putting interface up takes a bit longer,
I was measuring ~500 ms during interface up.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/bmi.c | 5 +++++
drivers/net/wireless/ath/ath6kl/bmi.h | 2 ++
drivers/net/wireless/ath/ath6kl/core.h | 4 ++++
drivers/net/wireless/ath/ath6kl/htc.c | 3 +++
drivers/net/wireless/ath/ath6kl/init.c | 35 +++++++++++++++++++++++++++++---
drivers/net/wireless/ath/ath6kl/main.c | 22 ++++++++++++++++----
6 files changed, 64 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c
index 5a4c24d..a962fe4 100644
--- a/drivers/net/wireless/ath/ath6kl/bmi.c
+++ b/drivers/net/wireless/ath/ath6kl/bmi.c
@@ -670,6 +670,11 @@ int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
return ret;
}
+void ath6kl_bmi_reset(struct ath6kl *ar)
+{
+ ar->bmi.done_sent = false;
+}
+
int ath6kl_bmi_init(struct ath6kl *ar)
{
ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC);
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h
index 96851d5..009e8f6 100644
--- a/drivers/net/wireless/ath/ath6kl/bmi.h
+++ b/drivers/net/wireless/ath/ath6kl/bmi.h
@@ -230,6 +230,8 @@ struct ath6kl_bmi_target_info {
int ath6kl_bmi_init(struct ath6kl *ar);
void ath6kl_bmi_cleanup(struct ath6kl *ar);
+void ath6kl_bmi_reset(struct ath6kl *ar);
+
int ath6kl_bmi_done(struct ath6kl *ar);
int ath6kl_bmi_get_target_info(struct ath6kl *ar,
struct ath6kl_bmi_target_info *targ_info);
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 5ac415e..1ac0dd1 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -447,6 +447,7 @@ enum ath6kl_dev_state {
DESTROY_IN_PROGRESS,
SKIP_SCAN,
ROAM_TBL_PEND,
+ FIRST_BOOT,
};
struct ath6kl {
@@ -662,4 +663,7 @@ void ath6kl_deinit_if_data(struct ath6kl_vif *vif);
void ath6kl_core_free(struct ath6kl *ar);
struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready);
+int ath6kl_init_hw_start(struct ath6kl *ar);
+int ath6kl_init_hw_stop(struct ath6kl *ar);
+
#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c
index 04b4070..99220d4 100644
--- a/drivers/net/wireless/ath/ath6kl/htc.c
+++ b/drivers/net/wireless/ath/ath6kl/htc.c
@@ -2622,6 +2622,9 @@ int ath6kl_htc_start(struct htc_target *target)
struct htc_packet *packet;
int status;
+ memset(&target->dev->irq_proc_reg, 0,
+ sizeof(target->dev->irq_proc_reg));
+
/* Disable interrupts at the chip level */
ath6kl_hif_disable_intrs(target->dev);
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index a0b81c3..c197e4c 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1421,11 +1421,13 @@ static int ath6kl_init_hw_params(struct ath6kl *ar)
return 0;
}
-static int ath6kl_hw_start(struct ath6kl *ar)
+int ath6kl_init_hw_start(struct ath6kl *ar)
{
long timeleft;
int ret, i;
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n");
+
ret = ath6kl_hif_power_on(ar);
if (ret)
return ret;
@@ -1517,6 +1519,25 @@ err_power_off:
return ret;
}
+int ath6kl_init_hw_stop(struct ath6kl *ar)
+{
+ int ret;
+
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "hw stop\n");
+
+ ath6kl_htc_stop(ar->htc_target);
+
+ ath6kl_hif_stop(ar);
+
+ ath6kl_bmi_reset(ar);
+
+ ret = ath6kl_hif_power_off(ar);
+ if (ret)
+ ath6kl_warn("failed to power off hif: %d\n", ret);
+
+ return 0;
+}
+
int ath6kl_core_init(struct ath6kl *ar)
{
struct ath6kl_bmi_target_info targ_info;
@@ -1628,9 +1649,11 @@ int ath6kl_core_init(struct ath6kl *ar)
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
- ret = ath6kl_hw_start(ar);
+ set_bit(FIRST_BOOT, &ar->flag);
+
+ ret = ath6kl_init_hw_start(ar);
if (ret) {
- ath6kl_err("Failed to boot hardware: %d\n", ret);
+ ath6kl_err("Failed to start hardware: %d\n", ret);
goto err_rxbuf_cleanup;
}
@@ -1640,6 +1663,12 @@ int ath6kl_core_init(struct ath6kl *ar)
*/
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
+ ret = ath6kl_init_hw_stop(ar);
+ if (ret) {
+ ath6kl_err("Failed to stop hardware: %d\n", ret);
+ goto err_htc_cleanup;
+ }
+
return ret;
err_rxbuf_cleanup:
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 3b2a7e8..717ed22 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -673,10 +673,12 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
set_bit(WMI_READY, &ar->flag);
wake_up(&ar->event_wq);
- ath6kl_info("hw %s fw %s%s\n",
- get_hw_id_string(ar->wiphy->hw_version),
- ar->wiphy->fw_version,
- test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
+ if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) {
+ ath6kl_info("hw %s fw %s%s\n",
+ get_hw_id_string(ar->wiphy->hw_version),
+ ar->wiphy->fw_version,
+ test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
+ }
}
void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)
@@ -1112,6 +1114,12 @@ struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar)
static int ath6kl_open(struct net_device *dev)
{
struct ath6kl_vif *vif = netdev_priv(dev);
+ int ret;
+
+ /* FIXME: how to handle multi vif support? */
+ ret = ath6kl_init_hw_start(vif->ar);
+ if (ret)
+ return ret;
set_bit(WLAN_ENABLED, &vif->flags);
@@ -1128,6 +1136,7 @@ static int ath6kl_close(struct net_device *dev)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
+ int ret;
netif_stop_queue(dev);
@@ -1143,6 +1152,11 @@ static int ath6kl_close(struct net_device *dev)
ath6kl_cfg80211_scan_complete_event(vif, -ECANCELED);
+ /* FIXME: how to handle multi vif support? */
+ ret = ath6kl_init_hw_stop(ar);
+ if (ret)
+ return ret;
+
return 0;
}
^ permalink raw reply related
* [PATCH 1/5] ath6kl: create ath6kl_hif_stop()
From: Kalle Valo @ 2011-10-30 19:15 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
In-Reply-To: <20111030190922.20466.299.stgit@localhost6.localdomain6>
This is to reset hif layer for powering down hw.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath6kl/hif-ops.h | 7 +++++
drivers/net/wireless/ath/ath6kl/hif.h | 1 +
drivers/net/wireless/ath/ath6kl/sdio.c | 45 +++++++++++++++++++++++++++++
3 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h
index 34adc77..50fd3e9 100644
--- a/drivers/net/wireless/ath/ath6kl/hif-ops.h
+++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h
@@ -111,4 +111,11 @@ static inline int ath6kl_hif_power_off(struct ath6kl *ar)
return ar->hif_ops->power_off(ar);
}
+static inline void ath6kl_hif_stop(struct ath6kl *ar)
+{
+ ath6kl_dbg(ATH6KL_DBG_HIF, "hif stop\n");
+
+ ar->hif_ops->stop(ar);
+}
+
#endif
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h
index 78a6c79..814386d 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.h
+++ b/drivers/net/wireless/ath/ath6kl/hif.h
@@ -246,6 +246,7 @@ struct ath6kl_hif_ops {
int (*resume)(struct ath6kl *ar);
int (*power_on)(struct ath6kl *ar);
int (*power_off)(struct ath6kl *ar);
+ void (*stop)(struct ath6kl *ar);
};
int ath6kl_hif_setup(struct ath6kl_device *dev);
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 682c47c..c61c512 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -45,6 +45,8 @@ struct ath6kl_sdio {
struct list_head scat_req;
spinlock_t scat_lock;
+ bool scatter_enabled;
+
bool is_disabled;
atomic_t irq_handling;
const struct sdio_device_id *id;
@@ -651,6 +653,11 @@ static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar)
list_del(&s_req->list);
spin_unlock_bh(&ar_sdio->scat_lock);
+ /*
+ * FIXME: should we also call completion handler with
+ * ath6kl_hif_rw_comp_handler() with status -ECANCELED so
+ * that the packet is properly freed?
+ */
if (s_req->busrequest)
ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest);
kfree(s_req->virt_dma_buf);
@@ -670,6 +677,11 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
int ret;
bool virt_scat = false;
+ if (ar_sdio->scatter_enabled)
+ return 0;
+
+ ar_sdio->scatter_enabled = true;
+
/* check if host supports scatter and it meets our requirements */
if (ar_sdio->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) {
ath6kl_err("host only supports scatter of :%d entries, need: %d\n",
@@ -762,6 +774,38 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
return 0;
}
+static void ath6kl_sdio_stop(struct ath6kl *ar)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ struct bus_request *req, *tmp_req;
+ void *context;
+
+ /* FIXME: make sure that wq is not queued again */
+
+ cancel_work_sync(&ar_sdio->wr_async_work);
+
+ spin_lock_bh(&ar_sdio->wr_async_lock);
+
+ list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
+ list_del(&req->list);
+
+ if (req->scat_req) {
+ /* this is a scatter gather request */
+ req->scat_req->status = -ECANCELED;
+ req->scat_req->complete(ar_sdio->ar->htc_target,
+ req->scat_req);
+ } else {
+ context = req->packet;
+ ath6kl_sdio_free_bus_req(ar_sdio, req);
+ ath6kl_hif_rw_comp_handler(context, -ECANCELED);
+ }
+ }
+
+ spin_unlock_bh(&ar_sdio->wr_async_lock);
+
+ WARN_ON(get_queue_depth(&ar_sdio->scat_req) != 4);
+}
+
static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
.read_write_sync = ath6kl_sdio_read_write_sync,
.write_async = ath6kl_sdio_write_async,
@@ -776,6 +820,7 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
.resume = ath6kl_sdio_resume,
.power_on = ath6kl_sdio_power_on,
.power_off = ath6kl_sdio_power_off,
+ .stop = ath6kl_sdio_stop,
};
static int ath6kl_sdio_probe(struct sdio_func *func,
^ permalink raw reply related
* [PATCH 0/5] ath6kl: cut power when interface is down
From: Kalle Valo @ 2011-10-30 19:15 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless
The following series changes interface handling so that power is
cut from the chip whenever interface is down compared to the current
situation when the harware is powered all the time since module
is loaded.
I'm not really sure if this is going be the final implementation
but I'll send this for review anyway. I structured the code so that
it's easy to go back to the old functionality if we so desire.
Also I need to solve support for multivif. Currently these patches
work as there's only one vif.
---
Kalle Valo (5):
ath6kl: create ath6kl_hif_stop()
ath6kl: power down hardware when interface is down
ath6kl: fix WLAN_ENABLE usage in ath6kl_close()
ath6kl: print firmware crashes always
ath6kl: print seqno in htc debug logs
drivers/net/wireless/ath/ath6kl/bmi.c | 5 ++
drivers/net/wireless/ath/ath6kl/bmi.h | 2 +
drivers/net/wireless/ath/ath6kl/core.h | 5 +-
drivers/net/wireless/ath/ath6kl/hif-ops.h | 7 ++
drivers/net/wireless/ath/ath6kl/hif.c | 69 ++++++++++++++++++++--
drivers/net/wireless/ath/ath6kl/hif.h | 1
drivers/net/wireless/ath/ath6kl/htc.c | 14 +++--
drivers/net/wireless/ath/ath6kl/init.c | 90 ++++++++++-------------------
drivers/net/wireless/ath/ath6kl/main.c | 25 ++++++--
drivers/net/wireless/ath/ath6kl/sdio.c | 45 +++++++++++++++
10 files changed, 187 insertions(+), 76 deletions(-)
^ permalink raw reply
* Compat-wireless release for 2011-10-30 is baked
From: Compat-wireless cronjob account @ 2011-10-30 19:02 UTC (permalink / raw)
To: linux-wireless
compat-wireless code metrics
814862 - Total upstream lines of code being pulled
2431 - backport code changes
2113 - backport code additions
318 - backport code deletions
8588 - backport from compat module
11019 - total backport code
1.3523 - % of code consists of backport work
^ permalink raw reply
* [PATCH] compat-wireless build: build fix for renamed driver iwlagn -> iwlwifi
From: Oskari Simola @ 2011-10-30 16:02 UTC (permalink / raw)
To: linux-wireless
Hi,
Here is patch for compat-wireless build script to build correctly after
driver name change.
diff --git a/config.mk b/config.mk
index a71de4e..87bd16a 100644
--- a/config.mk
+++ b/config.mk
@@ -246,7 +246,7 @@ ifdef CONFIG_PCI
CONFIG_ATH5K_PCI=y
CONFIG_ATH9K_PCI=y
-CONFIG_IWLAGN=m
+CONFIG_IWLWIFI=m
# CONFIG_IWLWIFI_DEBUG=y
# CONFIG_IWLWIFI_DEBUGFS=y
# CONFIG_IWLWIFI_DEVICE_TRACING=y
diff --git a/scripts/driver-select b/scripts/driver-select
index 3619541..e280b4c 100755
--- a/scripts/driver-select
+++ b/scripts/driver-select
@@ -53,7 +53,7 @@ function usage {
echo -e "\t${CYAN}atheros${NORMAL} < ${PURPLE} ath5k ath9k
carl9170 zd1211rw ath6kl ${NORMAL}>"
echo -e "\t${CYAN}ath${NORMAL} < ${PURPLE} ath5k ath9k carl9170
ath6kl ${NORMAL}>"
echo -e "\t${CYAN}brcm80211${NORMAL} < ${PURPLE} brcmsmac
brcmfmac ${NORMAL}>"
- echo -e "\t${CYAN}iwlagn${NORMAL} < ${PURPLE} iwlagn ${NORMAL}>"
+ echo -e "\t${CYAN}iwlwifi${NORMAL} < ${PURPLE} iwlwifi ${NORMAL}>"
echo -e "\t${CYAN}rtl818x${NORMAL} < ${PURPLE} rtl8180 rtl8187
${NORMAL}>"
echo -e "\t${CYAN}rtlwifi${NORMAL} < ${PURPLE} rtl8192ce
${NORMAL}>"
echo -e "\t${CYAN}wl12xx${NORMAL} < ${PURPLE} wl1251 wl12xx
(SPI and SDIO)${NORMAL}>"
@@ -310,6 +310,7 @@ case $1 in
;;
intel)
select_drivers CONFIG_COMPAT_IWLWIFI \
+ CONFIG_IWLWIFI \
CONFIG_IPW
disable_staging
disable_var
@@ -317,8 +318,8 @@ case $1 in
disable_ethernet
disable_usbnet
;;
- iwlagn)
- select_driver CONFIG_IWLAGN
+ iwlwifi)
+ select_driver CONFIG_IWLWIFI
disable_staging
disable_var_01
disable_bt
^ permalink raw reply related
* [PATCH v2] mac80211: use min rate as basic rate for buggy APs
From: Eliad Peller @ 2011-10-30 13:41 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
Some buggy APs (and even P2P_GO) don't advertise their
basic rates in the association response.
In such case, use the min supported rate as the
basic rate.
Reported-by: Pontus Fuchs <pontus.fuchs@gmail.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: add debug print (Johannes)
net/mac80211/mlme.c | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0e5d8da..d3672e9 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1482,6 +1482,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
int i, j, err;
bool have_higher_than_11mbit = false;
u16 ap_ht_cap_flags;
+ int min_rate = INT_MAX, min_rate_index = -1;
/* AssocResp and ReassocResp have identical structure */
@@ -1537,6 +1538,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
rates |= BIT(j);
if (is_basic)
basic_rates |= BIT(j);
+ if (rate < min_rate) {
+ min_rate = rate;
+ min_rate_index = j;
+ }
break;
}
}
@@ -1554,11 +1559,25 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
rates |= BIT(j);
if (is_basic)
basic_rates |= BIT(j);
+ if (rate < min_rate) {
+ min_rate = rate;
+ min_rate_index = j;
+ }
break;
}
}
}
+ /*
+ * some buggy APs don't advertise basic_rates. use the lowest
+ * supported rate instead.
+ */
+ if (unlikely(!basic_rates) && min_rate_index >= 0) {
+ printk(KERN_DEBUG "%s: No basic rates in AssocResp. "
+ "Using min supported rate instead.\n", sdata->name);
+ basic_rates = BIT(min_rate_index);
+ }
+
sta->sta.supp_rates[wk->chan->band] = rates;
sdata->vif.bss_conf.basic_rates = basic_rates;
--
1.7.6.401.g6a319
^ permalink raw reply related
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