* Re: [RFC PATCH 0/6] zd1211rw: add support for AP mode
From: Jussi Kivilinna @ 2010-12-27 20:03 UTC (permalink / raw)
To: Jussi Kivilinna; +Cc: linux-wireless, Daniel Drake, Ulrich Kunitz
In-Reply-To: <20101227162850.560526dlr20mibwk@hayate.sektori.org>
Quoting Jussi Kivilinna <jussi.kivilinna@mbnet.fi>:
>
> I think problem is that hostapd/mon.wlan2 is getting monitor packets
> in wrong order. This causes hostapd to receive null-function packet
> from b43 at wrong time resulting 'Data/PS-poll frame from not
> associated STA xx:xx:xx:xx:xx:xx' message and disassociation. I
> pretty much don't have any idea why this happens and how to fix it.
> I have attached wireshark capture with monitor packets in wrong
> order.
Figured out the bug. Appears to be at zd1211rw/zd_mac.c:filter_ack() line:
for (i=1; i<position; i++) {
This should be:
for (i=1; i<=position; i++) {
Otherwise ack_wait_queue is never fully emptied by ACK packets.
I have also made other cleanups/fixes on zd1211rw that are not related
to AP-mode. Should I post AP-mode as own set and fixes as own?
-Jussi
^ permalink raw reply
* Compat-wireless release for 2010-12-27 is baked
From: Compat-wireless cronjob account @ 2010-12-27 20:05 UTC (permalink / raw)
To: linux-wireless
>From git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next
34367c7..a31d633 history -> origin/history
+ 6953948...23ffbb3 master -> origin/master (forced update)
8cad7f0..d7c1255 stable -> origin/stable
* [new tag] next-20101227 -> next-20101227
>From git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next
* [new tag] v2.6.37-rc7 -> v2.6.37-rc7
compat-wireless code metrics
774936 - Total upstream lines of code being pulled
^ permalink raw reply
* Re: [PATCH v2 09/18] wl1271: Configure AP on BSS info change
From: Arik Nemtsov @ 2010-12-27 21:46 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1293455515.19215.3052.camel@powerslave>
On Mon, Dec 27, 2010 at 15:11, Luciano Coelho <luciano.coelho@nokia.com> wrote:
> On Wed, 2010-12-22 at 16:27 +0200, ext Arik Nemtsov wrote:
>> Configure AP-specific beacon and probe response templates.
>> Start the AP when beaconing is enabled.
>>
>> Signed-off-by: Arik Nemtsov <arik@wizery.com>
>> ---
>
> [...]
>
>> static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
>> @@ -1898,73 +1900,84 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
>
> This whole wl1271_op_bss_info_changed() function was already quite long
> and hard to read. Now, with support for AP and STA, it got even worse.
> I think this should be broken down into smaller functions. No need to
> clean the whole function up now, but would it be possible to separate at
> least the AP and STA parts into separate functions?
Sounds like a good idea. I'll separate it into 3 functions - common,
ap and sta/ibss.
>
>
>> @@ -1983,11 +2018,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
>> bss_conf->cqm_rssi_thold,
>> bss_conf->cqm_rssi_hyst);
>> if (ret < 0)
>> - goto out;
>> + goto out_sleep;
>
> Hmmm, nice catch. We were going out without sleeping in case of error
> here. But this is a cross-patch change, could you separate it and send
> as a standalone patch?
Sure.
Regards,
Arik
^ permalink raw reply
* [PATCH] mac80211: ignore PSM bit of reordered frames
From: Christian Lamparter @ 2010-12-27 22:21 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
This patch tackles one of the problems of my
reorder release timer patch from August.
<http://www.spinics.net/lists/linux-wireless/msg57214.html>
=>
What if the reorder release triggers and ap_sta_ps_end
(called by ieee80211_rx_h_sta_process) accidentally clears
the WLAN_STA_PS_STA flag, because 100ms ago - when the STA
was still active - frames were put into the reorder buffer.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
---
RFC -> PATCH:
fix typo: DEFERED -> DEFERRED
---
net/mac80211/ieee80211_i.h | 2 ++
net/mac80211/rx.c | 4 ++++
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a0cf5ab..bb71fe3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -168,6 +168,7 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
* @IEEE80211_RX_FRAGMENTED: fragmented frame
* @IEEE80211_RX_AMSDU: a-MSDU packet
* @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed
+ * @IEEE80211_RX_DEFERRED_RELEASE: frame was subjected to receive reordering
*
* These are per-frame flags that are attached to a frame in the
* @rx_flags field of &struct ieee80211_rx_status.
@@ -178,6 +179,7 @@ enum ieee80211_packet_rx_flags {
IEEE80211_RX_FRAGMENTED = BIT(2),
IEEE80211_RX_AMSDU = BIT(3),
IEEE80211_RX_MALFORMED_ACTION_FRM = BIT(4),
+ IEEE80211_RX_DEFERRED_RELEASE = BIT(5),
};
/**
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b6c2a30..e612805 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -537,6 +537,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
struct sk_buff_head *frames)
{
struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
+ struct ieee80211_rx_status *status;
lockdep_assert_held(&tid_agg_rx->reorder_lock);
@@ -546,6 +547,8 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
/* release the frame from the reorder ring buffer */
tid_agg_rx->stored_mpdu_num--;
tid_agg_rx->reorder_buf[index] = NULL;
+ status = IEEE80211_SKB_RXCB(skb);
+ status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE;
__skb_queue_tail(frames, skb);
no_frame:
@@ -1185,6 +1188,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
* exchange sequence.
*/
if (!ieee80211_has_morefrags(hdr->frame_control) &&
+ !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
(rx->sdata->vif.type == NL80211_IFTYPE_AP ||
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
if (test_sta_flags(sta, WLAN_STA_PS_STA)) {
--
1.7.2.3
^ permalink raw reply related
* Re: printk %pV compatibility in b43 and ath for compat-wireless
From: Larry Finger @ 2010-12-27 22:22 UTC (permalink / raw)
To: Nick Leverton; +Cc: linux-wireless, Joe Perches
In-Reply-To: <loom.20101227T190514-850@post.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 3244 bytes --]
On 12/27/2010 12:05 PM, Nick Leverton wrote:
> Hi,
>
> I'm using compat-wireless with Debian 2.6.32 (kernel for forthcoming Debian 6.0
> release). It mostly works well but one thing that has crept in recently is the
> use of new printk features such as %pV which old kernels don't support. I
> noticed this whilst trying the new b43 n-phy code (for which much thanks to
> everyone involved), as I get kernel messages printed of the following form:
>
> Dec 23 21:10:46 nickl kernel: [688182.007780] Broadcom 43xx driver loaded [
> Features: PMNLS, Firmware-ID: FW13 ]
> Dec 23 21:10:50 nickl kernel: [688186.100195] b43-phy0: f535bb54
> Dec 23 21:10:50 nickl kernel: [688186.198711] ADDRCONF(NETDEV_UP): wlan0: link
> is not ready
> Dec 23 21:11:09 nickl kernel: [688205.048054] b43-phy0: f4a3bb54
> Dec 23 21:11:09 nickl kernel: [688205.145589] ADDRCONF(NETDEV_UP): wlan0: link
> is not ready
> Dec 23 21:11:20 nickl kernel: [688216.484744] ADDRCONF(NETDEV_CHANGE): wlan0:
> link becomes ready
> Dec 23 21:11:31 nickl kernel: [688225.667842] b43-phy0 ERROR: f56a5f34
> Dec 23 21:12:14 nickl kernel: [688235.585265] b43-phy0 ERROR: f56a5f34
> Dec 23 21:12:50 nickl kernel: [688270.140937] b43-phy0 ERROR: f56a5f34
> Dec 23 21:13:11 nickl kernel: [688306.427195] b43-phy0 ERROR: f56a5f34
> Dec 23 21:14:05 nickl kernel: [688327.492370] b43-phy0 ERROR: f56a5f34
> Dec 23 21:16:23 nickl kernel: [688381.712250] b43-phy0 ERROR: f56a5f34
> Dec 23 21:22:59 nickl kernel: [688518.942314] b43-phy0 ERROR: f56a5f34
> Dec 23 21:23:00 nickl kernel: [688529.935161] b43-phy0 ERROR: f56a5f34
>
> As of 20101223, the following code uses %pV, some of which can be seen above:
>
> ./drivers/net/wireless/b43/main.c: printk(KERN_INFO "b43-%s: %pV",
> ./drivers/net/wireless/b43/main.c: printk(KERN_ERR "b43-%s ERROR: %pV",
> ./drivers/net/wireless/b43/main.c: printk(KERN_WARNING "b43-%s
> warning: %pV",
> ./drivers/net/wireless/b43/main.c: printk(KERN_DEBUG "b43-%s debug: %pV",
> ./drivers/net/wireless/ath/main.c: rtn = printk("%sath: %pV", level,
> &vaf);
> ./drivers/net/wireless/b43legacy/main.c:
> printk(KERN_INFO "b43legacy-%s: %pV",
> ./drivers/net/wireless/b43legacy/main.c: printk(KERN_ERR "b43legacy-%s
> ERROR: %pV",
> ./drivers/net/wireless/b43legacy/main.c:
> printk(KERN_WARNING "b43legacy-%s warning: %pV",
> ./drivers/net/wireless/b43legacy/main.c: printk(KERN_DEBUG "b43legacy-%s
> debug: %pV",
>
> It would be useful to know the error message behind the vararg !
>
> I tried applying the patches which introduced %pV to kernel.org, but 2.6.32 is
> too old. Could this be fixed either in the compat b43 driver or in a compat
> back-feature, please ?
These changes were in commit #5b736d42.
I cannot fix them in compat-wireless, but I think I know the origin of those
errors. At present, b43 is not setting up the transmit header correctly for N
PHYs. Whenever, the rate-setting mechanism tries an OFDM rate, one of these
errors will occur. We are working on modifications to the driver to fix this.
Until we get that done, issue an 'iwconfig wlan0 rate 11M' to lock the interface
at 11 Mb/s.
The attached patch can be reverse-applied to fix the driver.
Larry
[-- Attachment #2: reverse_pV.patch --]
[-- Type: text/x-patch, Size: 2713 bytes --]
commit 5b736d42bc51fe893fd7d4ceac34c727d23135e1
Author: Joe Perches <joe@perches.com>
Date: Tue Nov 9 16:35:18 2010 -0800
drivers/net/wireless/b43/main.c: Use printf extension %pV
Using %pV reduces the number of printk calls and
eliminates any possible message interleaving from
other printk calls.
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index a118652..fa48803 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -322,59 +322,83 @@ static int b43_ratelimit(struct b43_wl *wl)
void b43info(struct b43_wl *wl, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
if (b43_modparam_verbose < B43_VERBOSITY_INFO)
return;
if (!b43_ratelimit(wl))
return;
+
va_start(args, fmt);
- printk(KERN_INFO "b43-%s: ",
- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_INFO "b43-%s: %pV",
+ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
va_end(args);
}
void b43err(struct b43_wl *wl, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
if (b43_modparam_verbose < B43_VERBOSITY_ERROR)
return;
if (!b43_ratelimit(wl))
return;
+
va_start(args, fmt);
- printk(KERN_ERR "b43-%s ERROR: ",
- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_ERR "b43-%s ERROR: %pV",
+ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
va_end(args);
}
void b43warn(struct b43_wl *wl, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
if (b43_modparam_verbose < B43_VERBOSITY_WARN)
return;
if (!b43_ratelimit(wl))
return;
+
va_start(args, fmt);
- printk(KERN_WARNING "b43-%s warning: ",
- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_WARNING "b43-%s warning: %pV",
+ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
va_end(args);
}
void b43dbg(struct b43_wl *wl, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
return;
+
va_start(args, fmt);
- printk(KERN_DEBUG "b43-%s debug: ",
- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_DEBUG "b43-%s debug: %pV",
+ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
va_end(args);
}
^ permalink raw reply related
* Re: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Bruno Randolf @ 2010-12-28 5:31 UTC (permalink / raw)
To: Johannes Berg; +Cc: linville, linux-wireless, mcgrof
In-Reply-To: <1293447459.3544.1.camel@jlt3.sipsolutions.net>
On Mon December 27 2010 19:57:39 Johannes Berg wrote:
> On Fri, 2010-12-24 at 16:44 +0900, Bruno Randolf wrote:
> > static bool freq_is_chan_12_13_14(u16 freq)
> > {
> >
> > - if (freq == ieee80211_channel_to_frequency(12) ||
> > - freq == ieee80211_channel_to_frequency(13) ||
> > - freq == ieee80211_channel_to_frequency(14))
> > + if (freq == ieee80211_channel_to_frequency(12, IEEE80211_BAND_2GHZ) ||
> > + freq == ieee80211_channel_to_frequency(13, IEEE80211_BAND_2GHZ) ||
> > + freq == ieee80211_channel_to_frequency(14, IEEE80211_BAND_2GHZ))
> >
> > return true;
>
> This seems strange ... why not just hardcode the values??
True, but this is not my code, I just did the change for the new function
parameter. It's in net/wireless/reg.c, so I'll CC: Luis.
> > if (freq->e == 0) {
> >
> > + int band = IEEE80211_BAND_2GHZ;
>
> enum?
Ok, thanks.
Any other comments on the code or purpose of this patch?
bruno
^ permalink raw reply
* Re: [PATCH v2 12/18] wl1271: AP mode - add STA add/remove ops
From: Arik Nemtsov @ 2010-12-28 5:37 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1293456859.19215.3072.camel@powerslave>
On Mon, Dec 27, 2010 at 15:34, Luciano Coelho <luciano.coelho@nokia.com> wrote:
> On Wed, 2010-12-22 at 16:27 +0200, ext Arik Nemtsov wrote:
>> Allocate and free host link IDs (HLIDs) for each link. A per-STA
>> data structure keeps the HLID of each STA.
>>
>> Signed-off-by: Arik Nemtsov <arik@wizery.com>
>> ---
>
> [...]
>
>> +static int wl1271_op_sta_add(struct ieee80211_hw *hw,
>> + struct ieee80211_vif *vif,
>> + struct ieee80211_sta *sta)
>> +{
>> + struct wl1271 *wl = hw->priv;
>> + int ret = 0;
>> + u8 hlid;
>> +
>> + mutex_lock(&wl->mutex);
>> +
>> + if (unlikely(wl->state == WL1271_STATE_OFF))
>> + goto out;
>> +
>> + if (wl->bss_type != BSS_TYPE_AP_BSS)
>> + goto out;
>
> Should we ever bump into these two conditions? Shouldn't we warn or
> return errors?
It will happen in IBSS as well, in which case we don't want to do anything.
>
>
>> +static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
>> + struct ieee80211_vif *vif,
>> + struct ieee80211_sta *sta)
>> +{
>> + struct wl1271 *wl = hw->priv;
>> + struct wl1271_station *wl_sta;
>> + int ret = 0;
>> +
>> + mutex_lock(&wl->mutex);
>> +
>> + if (unlikely(wl->state == WL1271_STATE_OFF))
>> + goto out;
>> +
>> + if (wl->bss_type != BSS_TYPE_AP_BSS)
>> + goto out;
>
> Same here...
As in the above :)
>
>
>> + wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
>> +
>> + ret = wl1271_ps_elp_wakeup(wl, false);
>> + if (ret < 0)
>> + goto out;
>> +
>> + wl_sta = (struct wl1271_station *)sta->drv_priv;
>> + ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid);
>> + if (ret < 0)
>> + goto out_sleep;
>
> Would it make sense to check if the sta is really in use (ie. it is
> marked in the ap_sta_map) before trying to remove it?
It does. I'll add the check.
Regards,
Arik
^ permalink raw reply
* Re: [PATCH v2 06/18] wl1271: AP mode - init sequence
From: Arik Nemtsov @ 2010-12-28 6:16 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1293454640.19215.3042.camel@powerslave>
On Mon, Dec 27, 2010 at 14:57, Luciano Coelho <luciano.coelho@nokia.com> wrote:
> On Wed, 2010-12-22 at 16:27 +0200, ext Arik Nemtsov wrote:
>> Split HW init sequence into AP/STA specific parts
>>
>> The AP specific init sequence includes configuration of templates, rate
>> classes, power mode, etc. Also unmask AP specific events in the event mbox.
>>
>> Separate the differences between AP and STA init into mode
>> specific functions called from wl1271_hw_init. The first is called after
>> radio configuration and the second after memory configuration.
>>
>> Signed-off-by: Arik Nemtsov <arik@wizery.com>
>> ---
>
> [...]
>
>> diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
>> index 02f843c..d51324d 100644
>> --- a/drivers/net/wireless/wl12xx/cmd.h
>> +++ b/drivers/net/wireless/wl12xx/cmd.h
>> @@ -140,6 +140,13 @@ enum cmd_templ {
>> * For CTS-to-self (FastCTS) mechanism
>> * for BT/WLAN coexistence (SoftGemini). */
>> CMD_TEMPL_ARP_RSP,
>> +
>> + /* AP-mode specific */
>> + CMD_TEMPL_AP_BEACON = 13,
>> + CMD_TEMPL_AP_PROBE_RESPONSE,
>> + CMD_TEMPL_AP_ARP_RSP,
>> + CMD_TEMPL_DEAUTH_AP,
>> +
>> CMD_TEMPL_MAX = 0xff
>> };
>
> Cool, I see that you fixed the issue we had before. Just one question,
> is the CMD_TEMPL_AP_ARP_RSP the same as the original CMD_TEMPL_ARP_RSP?
> I mean is it only the order in the enum that is different between the AP
> and the STA firmwares? If that's the case, we should *really* try to get
> this fixed in the AP firmware.
>
> It's still new enough and not so many people are using it yet, right? So
> it's the time to fix it if it makes sense.
Actually the AP and STA modes will be merged in one FW in the future.
So its already unified there.
Also note arp-filtering is only relevant for the STA role for now.
Only stations get the BSS_CHANGED_ARP_FILTER notification.
Implementing this for AP will require changes in mac80211.
>
>
>> diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
>> index 799c369..df6666b 100644
>> --- a/drivers/net/wireless/wl12xx/init.c
>> +++ b/drivers/net/wireless/wl12xx/init.c
>
> [...]
>
>> @@ -145,10 +253,6 @@ int wl1271_init_phy_config(struct wl1271 *wl)
>> if (ret < 0)
>> return ret;
>>
>> - ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
>> - if (ret < 0)
>> - return ret;
>> -
>
> Here we're changing the order of these initialization ACXs, but it
> shouldn't be a problem. If it is a problem, it's a firmware bug that
> (hopefully) can be fixed.
Haven't seen a problem with this one. Also note this ACX will be
reconfigured again on the first wl1271_op_configure_filter() call.
>
>
>> @@ -213,11 +317,150 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
>> return 0;
>> }
>>
>> +static int wl1271_sta_hw_init(struct wl1271 *wl)
>> +{
>> + int ret;
>> +
>> + ret = wl1271_cmd_ext_radio_parms(wl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = wl1271_sta_init_templates_config(wl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
>> + if (ret < 0)
>> + return ret;
>> +
>> + /* Initialize connection monitoring thresholds */
>> + ret = wl1271_acx_conn_monit_params(wl, false);
>> + if (ret < 0)
>> + return ret;
>> +
>> + /* Beacon filtering */
>> + ret = wl1271_init_beacon_filter(wl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + /* Bluetooth WLAN coexistence */
>> + ret = wl1271_init_pta(wl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + /* Beacons and boradcast settings */
>
> You copied the typo, maybe you could take the opportunity to fix it?
Sure.
>
>> + ret = wl1271_init_beacon_broadcast(wl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + /* Configure for ELP power saving */
>> + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
>> + if (ret < 0)
>> + return ret;
>> +
>> + /* Configure rssi/snr averaging weights */
>> + ret = wl1271_acx_rssi_snr_avg_weights(wl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = wl1271_acx_sta_rate_policies(wl);
>> + if (ret < 0)
>> + return ret;
>> +
>> + return 0;
>> +}
>
> Also here, this changes the initialization order a bit. I think this
> was Juuso's concern earlier. At least while we were having debug camps,
> the TI people supporting us were always asking us to be extremely
> cautious with the order of the initialization. They were saying that it
> was really important to do the initialization in the same way as the
> tiwlan driver does. Hopefully this is not an issue now...
We haven't encountered any issues in our internal testing (in both STA
and AP roles).
>
>
>> @@ -279,21 +512,11 @@ int wl1271_hw_init(struct wl1271 *wl)
>> if (ret < 0)
>> goto out_free_memmap;
>>
>> - /* Bluetooth WLAN coexistence */
>> - ret = wl1271_init_pta(wl);
>> - if (ret < 0)
>> - goto out_free_memmap;
>> -
>
> Just out of curiosity... Is AP coexistence with Bluetooth possible? This
> could be important in some scenarios.
It is possible and will be implemented in the future.
>
>
>> diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h
>> index 7762421..4d37210 100644
>> --- a/drivers/net/wireless/wl12xx/init.h
>> +++ b/drivers/net/wireless/wl12xx/init.h
>> @@ -27,10 +27,13 @@
>> #include "wl12xx.h"
>>
>> int wl1271_hw_init_power_auth(struct wl1271 *wl);
>> -int wl1271_init_templates_config(struct wl1271 *wl);
>> +int wl1271_sta_init_templates_config(struct wl1271 *wl);
>> int wl1271_init_phy_config(struct wl1271 *wl);
>> int wl1271_init_pta(struct wl1271 *wl);
>> int wl1271_init_energy_detection(struct wl1271 *wl);
>> int wl1271_hw_init(struct wl1271 *wl);
>>
>> +/* Functions from wl1271_main.c */
>> +u32 wl1271_min_rate_get(struct wl1271 *wl);
>> +
>
> This is bad and shouldn't be here. Need to find a better place for it.
How about tx.h? It's TX rate we're talking about here after all.
I can also change the name to wl1271_tx_min_rate_get().
>
>
>> diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h
>> index be21032..b230e72 100644
>> --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h
>> +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h
>> @@ -160,4 +160,9 @@ struct wl12xx_probe_resp_template {
>> struct wl12xx_ie_country country;
>> } __packed;
>>
>> +struct wl12xx_disconn_template {
>> + struct ieee80211_header header;
>> + __le16 disconn_reason;
>> +} __packed;
>> +
>
> Isn't padding necessary here to keep the struct 32-bit aligned?
AFAIK, templates should not be 32-bit aligned. Most of the templates
are not aligned.
Regards,
Arik
^ permalink raw reply
* Compile error for the last week inside rtlwifi/base.c
From: Weedy @ 2010-12-28 6:58 UTC (permalink / raw)
To: linux-wireless
I'm not sure if my kernel is too old or what but since nothing has changed I'm
going to ask.
CC [M]
/media/8G_SDcard/compat-wireless-2010-12-26-pc/drivers/net/wireless/rtlwifi/
base.o
/media/8G_SDcard/compat-wireless-2010-12-26-pc/drivers/net/wireless/rtlwifi/
base.c: In function ‘_rtl_init_deferred_work’:
/media/8G_SDcard/compat-wireless-2010-12-26-pc/drivers/net/wireless/rtlwifi/
base.c:229: error: implicit declaration of function ‘alloc_workqueue’
/media/8G_SDcard/compat-wireless-2010-12-26-pc/drivers/net/wireless/rtlwifi/
base.c:229: warning: assignment makes pointer from integer without a cast
make[4]: *** [/media/8G_SDcard/compat-wireless-2010-12-26-pc/drivers/net/
wireless/rtlwifi/base.o] Error 1
make[3]: *** [/media/8G_SDcard/compat-wireless-2010-12-26-pc/drivers/net/
wireless/rtlwifi] Error 2
make[2]: *** [/media/8G_SDcard/compat-wireless-2010-12-26-pc/drivers/net/
wireless] Error 2
make[1]: *** [_module_/media/8G_SDcard/compat-wireless-2010-12-26-pc] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-2.6.35-24-generic-pae'
make: *** [modules] Error 2
^ permalink raw reply
* [PATCH] ath9k: Few clean ups in beacon config parameters
From: Mohammed Shafi Shajakhan @ 2010-12-28 7:36 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, lrodriguez, Mohammed Shafi Shajakhan
From: Mohammed Shafi Shajakhan <mshajakhan@atheros.com>
Some minor clean ups in assigning values to beacon config parameters
Signed-off-by: Mohammed Shafi Shajakhan <mshajakhan@atheros.com>
---
drivers/net/wireless/ath/ath9k/beacon.c | 25 +++++++++++++------------
1 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 5e108c0..385ba03 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -566,8 +566,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
* last beacon we received (which may be none).
*/
dtimperiod = conf->dtim_period;
- if (dtimperiod <= 0) /* NB: 0 if not known */
- dtimperiod = 1;
dtimcount = conf->dtim_count;
if (dtimcount >= dtimperiod) /* NB: sanity check */
dtimcount = 0;
@@ -575,8 +573,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
cfpcount = 0;
sleepduration = conf->listen_interval * intval;
- if (sleepduration <= 0)
- sleepduration = intval;
/*
* Pull nexttbtt forward to reflect the current
@@ -662,8 +658,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
}
static void ath_beacon_config_adhoc(struct ath_softc *sc,
- struct ath_beacon_config *conf,
- struct ieee80211_vif *vif)
+ struct ath_beacon_config *conf)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -718,18 +713,17 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
/* Setup the beacon configuration parameters */
if (vif) {
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-
iftype = vif->type;
-
cur_conf->beacon_interval = bss_conf->beacon_int;
cur_conf->dtim_period = bss_conf->dtim_period;
+ } else {
+ iftype = sc->sc_ah->opmode;
+ }
+
cur_conf->listen_interval = 1;
cur_conf->dtim_count = 1;
cur_conf->bmiss_timeout =
ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
- } else {
- iftype = sc->sc_ah->opmode;
- }
/*
* It looks like mac80211 may end up using beacon interval of zero in
@@ -740,13 +734,20 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
if (cur_conf->beacon_interval == 0)
cur_conf->beacon_interval = 100;
+ /*
+ * Some times we dont parse dtim period from mac80211, in that case
+ * use a default value
+ */
+ if (cur_conf->dtim_period == 0)
+ cur_conf->dtim_period = 1;
+
switch (iftype) {
case NL80211_IFTYPE_AP:
ath_beacon_config_ap(sc, cur_conf);
break;
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
- ath_beacon_config_adhoc(sc, cur_conf, vif);
+ ath_beacon_config_adhoc(sc, cur_conf);
break;
case NL80211_IFTYPE_STATION:
ath_beacon_config_sta(sc, cur_conf);
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/5] ath9k_htc: Fix warning on device removal
From: Sujith @ 2010-12-28 8:11 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Sujith.Manoharan
From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
The commit "ath9k_hw: warn if we cannot change the power to the chip"
introduced a new warning to indicate chip powerup failures, but this
is not required for devices that have been removed. Handle USB device
removal properly by checking for unplugged status.
For PCI devices, this warning will still be seen when the card is pulled
out, not sure how to check for card removal.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/eeprom.h | 2 --
drivers/net/wireless/ath/ath9k/hif_usb.c | 6 +++---
drivers/net/wireless/ath/ath9k/htc.h | 5 ++---
drivers/net/wireless/ath/ath9k/htc_drv_init.c | 5 +----
drivers/net/wireless/ath/ath9k/hw.c | 4 +++-
drivers/net/wireless/ath/ath9k/hw.h | 4 ++++
drivers/net/wireless/ath/ath9k/wmi.c | 2 +-
7 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index f6f09d1..58e2ddc 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -23,8 +23,6 @@
#include <net/cfg80211.h>
#include "ar9003_eeprom.h"
-#define AH_USE_EEPROM 0x1
-
#ifdef __BIG_ENDIAN
#define AR5416_EEPROM_MAGIC 0x5aa5
#else
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 22b68b3..c20c8c8 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -993,16 +993,16 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
+ bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false;
if (hif_dev) {
- ath9k_htc_hw_deinit(hif_dev->htc_handle,
- (udev->state == USB_STATE_NOTATTACHED) ? true : false);
+ ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
ath9k_htc_hw_free(hif_dev->htc_handle);
ath9k_hif_usb_dev_deinit(hif_dev);
usb_set_intfdata(interface, NULL);
}
- if (hif_dev->flags & HIF_USB_START)
+ if (!unplugged && (hif_dev->flags & HIF_USB_START))
ath9k_hif_usb_reboot(udev);
kfree(hif_dev);
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index fdf9d5f..e6c2f0a 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -339,9 +339,8 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv);
#define OP_ASSOCIATED BIT(7)
#define OP_ENABLE_BEACON BIT(8)
#define OP_LED_DEINIT BIT(9)
-#define OP_UNPLUGGED BIT(10)
-#define OP_BT_PRIORITY_DETECTED BIT(11)
-#define OP_BT_SCAN BIT(12)
+#define OP_BT_PRIORITY_DETECTED BIT(10)
+#define OP_BT_SCAN BIT(11)
struct ath9k_htc_priv {
struct device *dev;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 0f6be35..724f545 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -851,9 +851,6 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
if (ret)
goto err_init;
- /* The device may have been unplugged earlier. */
- priv->op_flags &= ~OP_UNPLUGGED;
-
ret = ath9k_init_device(priv, devid, product, drv_info);
if (ret)
goto err_init;
@@ -873,7 +870,7 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
/* Check if the device has been yanked out. */
if (hotunplug)
- htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
+ htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
ath9k_deinit_device(htc_handle->drv_priv);
ath9k_deinit_wmi(htc_handle->drv_priv);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 4b51ed4..fde9786 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1615,7 +1615,9 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
* simply keep the ATH_DBG_WARN_ON_ONCE() but make
* ath9k_hw_setpower() return type void.
*/
- ATH_DBG_WARN_ON_ONCE(!status);
+
+ if (!(ah->ah_flags & AH_UNPLUGGED))
+ ATH_DBG_WARN_ON_ONCE(!status);
return status;
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index b8ffaa5..5a3dfec 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -646,6 +646,10 @@ struct ath_nf_limits {
s16 nominal;
};
+/* ah_flags */
+#define AH_USE_EEPROM 0x1
+#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
+
struct ath_hw {
struct ieee80211_hw *hw;
struct ath_common common;
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 8f42ea7..573daca 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -250,7 +250,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
int time_left, ret = 0;
unsigned long flags;
- if (wmi->drv_priv->op_flags & OP_UNPLUGGED)
+ if (ah->ah_flags & AH_UNPLUGGED)
return 0;
skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC);
--
1.7.3.4
^ permalink raw reply related
* [PATCH 2/5] ath9k_htc: Handle pending URBs properly
From: Sujith @ 2010-12-28 8:11 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Sujith.Manoharan
From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
When doing a channel change, the pending URBs have to be killed
properly on calling htc_stop().
This fixes the probe response timeout seen when sending UDP traffic at
a high rate and running background scan at the same time.
Cc: stable <stable@kernel.org>
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/hif_usb.c | 40 +++++++++++++++++++++++++++---
drivers/net/wireless/ath/ath9k/hif_usb.h | 1 +
2 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index c20c8c8..5ab3084 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -153,16 +153,36 @@ static void hif_usb_tx_cb(struct urb *urb)
case -ENODEV:
case -ESHUTDOWN:
/*
- * The URB has been killed, free the SKBs
- * and return.
+ * The URB has been killed, free the SKBs.
*/
ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
- return;
+
+ /*
+ * If the URBs are being flushed, no need to add this
+ * URB to the free list.
+ */
+ spin_lock(&hif_dev->tx.tx_lock);
+ if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
+ spin_unlock(&hif_dev->tx.tx_lock);
+ return;
+ }
+ spin_unlock(&hif_dev->tx.tx_lock);
+
+ /*
+ * In the stop() case, this URB has to be added to
+ * the free list.
+ */
+ goto add_free;
default:
break;
}
- /* Check if TX has been stopped */
+ /*
+ * Check if TX has been stopped, this is needed because
+ * this CB could have been invoked just after the TX lock
+ * was released in hif_stop() and kill_urb() hasn't been
+ * called yet.
+ */
spin_lock(&hif_dev->tx.tx_lock);
if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
spin_unlock(&hif_dev->tx.tx_lock);
@@ -314,6 +334,7 @@ static void hif_usb_start(void *hif_handle, u8 pipe_id)
static void hif_usb_stop(void *hif_handle, u8 pipe_id)
{
struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
+ struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
unsigned long flags;
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
@@ -321,6 +342,12 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id)
hif_dev->tx.tx_skb_cnt = 0;
hif_dev->tx.flags |= HIF_USB_TX_STOP;
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
+
+ /* The pending URBs have to be canceled. */
+ list_for_each_entry_safe(tx_buf, tx_buf_tmp,
+ &hif_dev->tx.tx_pending, list) {
+ usb_kill_urb(tx_buf->urb);
+ }
}
static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
@@ -587,6 +614,7 @@ free:
static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
{
struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
+ unsigned long flags;
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
&hif_dev->tx.tx_buf, list) {
@@ -597,6 +625,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
kfree(tx_buf);
}
+ spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
+ hif_dev->tx.flags |= HIF_USB_TX_FLUSH;
+ spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
+
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
&hif_dev->tx.tx_pending, list) {
usb_kill_urb(tx_buf->urb);
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index e4a5e2e..7b9d863 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -64,6 +64,7 @@ struct tx_buf {
};
#define HIF_USB_TX_STOP BIT(0)
+#define HIF_USB_TX_FLUSH BIT(1)
struct hif_usb_tx {
u8 flags;
--
1.7.3.4
^ permalink raw reply related
* [PATCH 3/5] ath9k_htc: Handle FATAL events
From: Sujith @ 2010-12-28 8:12 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Sujith.Manoharan
From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
The device has to be reset when a FATAL event is received.
Not doing so would leave the card in a non-working state.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/htc.h | 6 ++-
drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 ++-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 57 ++++++++++++++++++++++++-
drivers/net/wireless/ath/ath9k/wmi.c | 18 +++++++-
drivers/net/wireless/ath/ath9k/wmi.h | 3 +-
5 files changed, 84 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index e6c2f0a..1062274 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -377,7 +377,7 @@ struct ath9k_htc_priv {
struct ieee80211_vif *vif;
struct htc_beacon_config cur_beacon_conf;
unsigned int rxfilter;
- struct tasklet_struct wmi_tasklet;
+ struct tasklet_struct swba_tasklet;
struct tasklet_struct rx_tasklet;
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
struct ath9k_htc_rx rx;
@@ -385,6 +385,7 @@ struct ath9k_htc_priv {
struct sk_buff_head tx_queue;
struct delayed_work ath9k_ani_work;
struct work_struct ps_work;
+ struct work_struct fatal_work;
struct mutex htc_pm_lock;
unsigned long ps_usecount;
@@ -419,6 +420,8 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
common->bus_ops->read_cachesize(common, csz);
}
+void ath9k_htc_reset(struct ath9k_htc_priv *priv);
+
void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif);
@@ -434,6 +437,7 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
void ath9k_htc_station_work(struct work_struct *work);
void ath9k_htc_aggr_work(struct work_struct *work);
void ath9k_ani_work(struct work_struct *work);;
+void ath_start_ani(struct ath9k_htc_priv *priv);
int ath9k_tx_init(struct ath9k_htc_priv *priv);
void ath9k_tx_tasklet(unsigned long data);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 724f545..9150ca6 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -142,7 +142,7 @@ static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
{
ath9k_htc_exit_debug(priv->ah);
ath9k_hw_deinit(priv->ah);
- tasklet_kill(&priv->wmi_tasklet);
+ tasklet_kill(&priv->swba_tasklet);
tasklet_kill(&priv->rx_tasklet);
tasklet_kill(&priv->tx_tasklet);
kfree(priv->ah);
@@ -647,13 +647,15 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
spin_lock_init(&priv->tx_lock);
mutex_init(&priv->mutex);
mutex_init(&priv->htc_pm_lock);
- tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
+ tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet,
(unsigned long)priv);
tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
(unsigned long)priv);
- tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
+ tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
+ (unsigned long)priv);
INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
INIT_WORK(&priv->ps_work, ath9k_ps_work);
+ INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
/*
* Cache line size is used to size and align various
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index dd17909..1b1be72 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -116,6 +116,60 @@ void ath9k_ps_work(struct work_struct *work)
ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
}
+void ath9k_htc_reset(struct ath9k_htc_priv *priv)
+{
+ struct ath_hw *ah = priv->ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_channel *channel = priv->hw->conf.channel;
+ struct ath9k_hw_cal_data *caldata;
+ enum htc_phymode mode;
+ __be16 htc_mode;
+ u8 cmd_rsp;
+ int ret;
+
+ mutex_lock(&priv->mutex);
+ ath9k_htc_ps_wakeup(priv);
+
+ if (priv->op_flags & OP_ASSOCIATED)
+ cancel_delayed_work_sync(&priv->ath9k_ani_work);
+
+ ieee80211_stop_queues(priv->hw);
+ htc_stop(priv->htc);
+ WMI_CMD(WMI_DISABLE_INTR_CMDID);
+ WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
+ WMI_CMD(WMI_STOP_RECV_CMDID);
+
+ caldata = &priv->caldata[channel->hw_value];
+ ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
+ if (ret) {
+ ath_err(common,
+ "Unable to reset device (%u Mhz) reset status %d\n",
+ channel->center_freq, ret);
+ }
+
+ ath_update_txpow(priv);
+
+ WMI_CMD(WMI_START_RECV_CMDID);
+ ath9k_host_rx_init(priv);
+
+ mode = ath9k_htc_get_curmode(priv, ah->curchan);
+ htc_mode = cpu_to_be16(mode);
+ WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
+
+ WMI_CMD(WMI_ENABLE_INTR_CMDID);
+ htc_start(priv->htc);
+
+ if (priv->op_flags & OP_ASSOCIATED) {
+ ath9k_htc_beacon_config(priv, priv->vif);
+ ath_start_ani(priv);
+ }
+
+ ieee80211_wake_queues(priv->hw);
+
+ ath9k_htc_ps_restore(priv);
+ mutex_unlock(&priv->mutex);
+}
+
static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
struct ieee80211_hw *hw,
struct ath9k_channel *hchan)
@@ -690,7 +744,7 @@ void ath9k_htc_debug_remove_root(void)
/* ANI */
/*******/
-static void ath_start_ani(struct ath9k_htc_priv *priv)
+void ath_start_ani(struct ath9k_htc_priv *priv)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -1227,6 +1281,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
}
/* Cancel all the running timers/work .. */
+ cancel_work_sync(&priv->fatal_work);
cancel_work_sync(&priv->ps_work);
cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
ath9k_led_stop_brightness(priv);
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 573daca..dc862f5 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -120,7 +120,7 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
kfree(priv->wmi);
}
-void ath9k_wmi_tasklet(unsigned long data)
+void ath9k_swba_tasklet(unsigned long data)
{
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -131,6 +131,16 @@ void ath9k_wmi_tasklet(unsigned long data)
}
+void ath9k_fatal_work(struct work_struct *work)
+{
+ struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+ fatal_work);
+ struct ath_common *common = ath9k_hw_common(priv->ah);
+
+ ath_dbg(common, ATH_DBG_FATAL, "FATAL Event received, resetting device\n");
+ ath9k_htc_reset(priv);
+}
+
static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb)
{
skb_pull(skb, sizeof(struct wmi_cmd_hdr));
@@ -163,7 +173,11 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
switch (cmd_id) {
case WMI_SWBA_EVENTID:
wmi->beacon_pending = *(u8 *)wmi_event;
- tasklet_schedule(&wmi->drv_priv->wmi_tasklet);
+ tasklet_schedule(&wmi->drv_priv->swba_tasklet);
+ break;
+ case WMI_FATAL_EVENTID:
+ ieee80211_queue_work(wmi->drv_priv->hw,
+ &wmi->drv_priv->fatal_work);
break;
case WMI_TXRATE_EVENTID:
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h
index ac61074..4208427 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.h
+++ b/drivers/net/wireless/ath/ath9k/wmi.h
@@ -117,7 +117,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
u8 *cmd_buf, u32 cmd_len,
u8 *rsp_buf, u32 rsp_len,
u32 timeout);
-void ath9k_wmi_tasklet(unsigned long data);
+void ath9k_swba_tasklet(unsigned long data);
+void ath9k_fatal_work(struct work_struct *work);
#define WMI_CMD(_wmi_cmd) \
do { \
--
1.7.3.4
^ permalink raw reply related
* [PATCH 4/5] ath9k_htc: Fix fast channel change
From: Sujith @ 2010-12-28 8:12 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Sujith.Manoharan
From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
When returning to the operating channel, a full HW
reset has to be done instead of a fast channel change.
Since sw_scan_complete() is called after the config() call for the
home channel, we end up doing a FCC. Fix this issue by checking
the OFFCHANNEL flag to determine FCC.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/htc.h | 19 +++++++++----------
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 8 ++------
2 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 1062274..34456a8 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -331,16 +331,15 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv);
#define OP_INVALID BIT(0)
#define OP_SCANNING BIT(1)
-#define OP_FULL_RESET BIT(2)
-#define OP_LED_ASSOCIATED BIT(3)
-#define OP_LED_ON BIT(4)
-#define OP_PREAMBLE_SHORT BIT(5)
-#define OP_PROTECT_ENABLE BIT(6)
-#define OP_ASSOCIATED BIT(7)
-#define OP_ENABLE_BEACON BIT(8)
-#define OP_LED_DEINIT BIT(9)
-#define OP_BT_PRIORITY_DETECTED BIT(10)
-#define OP_BT_SCAN BIT(11)
+#define OP_LED_ASSOCIATED BIT(2)
+#define OP_LED_ON BIT(3)
+#define OP_PREAMBLE_SHORT BIT(4)
+#define OP_PROTECT_ENABLE BIT(5)
+#define OP_ASSOCIATED BIT(6)
+#define OP_ENABLE_BEACON BIT(7)
+#define OP_LED_DEINIT BIT(8)
+#define OP_BT_PRIORITY_DETECTED BIT(9)
+#define OP_BT_SCAN BIT(10)
struct ath9k_htc_priv {
struct device *dev;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 1b1be72..d54adeb 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -177,7 +177,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
- bool fastcc = true;
+ bool fastcc;
struct ieee80211_channel *channel = hw->conf.channel;
struct ath9k_hw_cal_data *caldata;
enum htc_phymode mode;
@@ -188,8 +188,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
if (priv->op_flags & OP_INVALID)
return -EIO;
- if (priv->op_flags & OP_FULL_RESET)
- fastcc = false;
+ fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
ath9k_htc_ps_wakeup(priv);
htc_stop(priv->htc);
@@ -231,8 +230,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
goto err;
htc_start(priv->htc);
-
- priv->op_flags &= ~OP_FULL_RESET;
err:
ath9k_htc_ps_restore(priv);
return ret;
@@ -1847,7 +1844,6 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
spin_lock_bh(&priv->beacon_lock);
priv->op_flags &= ~OP_SCANNING;
spin_unlock_bh(&priv->beacon_lock);
- priv->op_flags |= OP_FULL_RESET;
if (priv->op_flags & OP_ASSOCIATED) {
ath9k_htc_beacon_config(priv, priv->vif);
ath_start_ani(priv);
--
1.7.3.4
^ permalink raw reply related
* [PATCH 5/5] ath9k_htc: Move LED/RFKILL code to htc_drv_gpio.c
From: Sujith @ 2010-12-28 8:12 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Sujith.Manoharan
From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
And add the copyright/license header.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/htc.h | 5 +
drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 327 +++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 313 +-----------------------
3 files changed, 333 insertions(+), 312 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 34456a8..a099b3e 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -459,8 +459,13 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv);
void ath9k_ps_work(struct work_struct *work);
bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
enum ath9k_power_mode mode);
+void ath_update_txpow(struct ath9k_htc_priv *priv);
void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
+void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
+void ath9k_htc_radio_enable(struct ieee80211_hw *hw);
+void ath9k_htc_radio_disable(struct ieee80211_hw *hw);
+void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv);
void ath9k_init_leds(struct ath9k_htc_priv *priv);
void ath9k_deinit_leds(struct ath9k_htc_priv *priv);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index 283ff97..fe70f67 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (c) 2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
#include "htc.h"
/******************/
@@ -131,3 +147,314 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
cancel_delayed_work_sync(&priv->coex_period_work);
cancel_delayed_work_sync(&priv->duty_cycle_work);
}
+
+/*******/
+/* LED */
+/*******/
+
+static void ath9k_led_blink_work(struct work_struct *work)
+{
+ struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+ ath9k_led_blink_work.work);
+
+ if (!(priv->op_flags & OP_LED_ASSOCIATED))
+ return;
+
+ if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
+ (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
+ ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
+ else
+ ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
+ (priv->op_flags & OP_LED_ON) ? 1 : 0);
+
+ ieee80211_queue_delayed_work(priv->hw,
+ &priv->ath9k_led_blink_work,
+ (priv->op_flags & OP_LED_ON) ?
+ msecs_to_jiffies(priv->led_off_duration) :
+ msecs_to_jiffies(priv->led_on_duration));
+
+ priv->led_on_duration = priv->led_on_cnt ?
+ max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) :
+ ATH_LED_ON_DURATION_IDLE;
+ priv->led_off_duration = priv->led_off_cnt ?
+ max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) :
+ ATH_LED_OFF_DURATION_IDLE;
+ priv->led_on_cnt = priv->led_off_cnt = 0;
+
+ if (priv->op_flags & OP_LED_ON)
+ priv->op_flags &= ~OP_LED_ON;
+ else
+ priv->op_flags |= OP_LED_ON;
+}
+
+static void ath9k_led_brightness_work(struct work_struct *work)
+{
+ struct ath_led *led = container_of(work, struct ath_led,
+ brightness_work.work);
+ struct ath9k_htc_priv *priv = led->priv;
+
+ switch (led->brightness) {
+ case LED_OFF:
+ if (led->led_type == ATH_LED_ASSOC ||
+ led->led_type == ATH_LED_RADIO) {
+ ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
+ (led->led_type == ATH_LED_RADIO));
+ priv->op_flags &= ~OP_LED_ASSOCIATED;
+ if (led->led_type == ATH_LED_RADIO)
+ priv->op_flags &= ~OP_LED_ON;
+ } else {
+ priv->led_off_cnt++;
+ }
+ break;
+ case LED_FULL:
+ if (led->led_type == ATH_LED_ASSOC) {
+ priv->op_flags |= OP_LED_ASSOCIATED;
+ ieee80211_queue_delayed_work(priv->hw,
+ &priv->ath9k_led_blink_work, 0);
+ } else if (led->led_type == ATH_LED_RADIO) {
+ ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
+ priv->op_flags |= OP_LED_ON;
+ } else {
+ priv->led_on_cnt++;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void ath9k_led_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
+ struct ath9k_htc_priv *priv = led->priv;
+
+ led->brightness = brightness;
+ if (!(priv->op_flags & OP_LED_DEINIT))
+ ieee80211_queue_delayed_work(priv->hw,
+ &led->brightness_work, 0);
+}
+
+void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
+{
+ cancel_delayed_work_sync(&priv->radio_led.brightness_work);
+ cancel_delayed_work_sync(&priv->assoc_led.brightness_work);
+ cancel_delayed_work_sync(&priv->tx_led.brightness_work);
+ cancel_delayed_work_sync(&priv->rx_led.brightness_work);
+}
+
+static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
+ char *trigger)
+{
+ int ret;
+
+ led->priv = priv;
+ led->led_cdev.name = led->name;
+ led->led_cdev.default_trigger = trigger;
+ led->led_cdev.brightness_set = ath9k_led_brightness;
+
+ ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev);
+ if (ret)
+ ath_err(ath9k_hw_common(priv->ah),
+ "Failed to register led:%s", led->name);
+ else
+ led->registered = 1;
+
+ INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
+
+ return ret;
+}
+
+static void ath9k_unregister_led(struct ath_led *led)
+{
+ if (led->registered) {
+ led_classdev_unregister(&led->led_cdev);
+ led->registered = 0;
+ }
+}
+
+void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
+{
+ priv->op_flags |= OP_LED_DEINIT;
+ ath9k_unregister_led(&priv->assoc_led);
+ priv->op_flags &= ~OP_LED_ASSOCIATED;
+ ath9k_unregister_led(&priv->tx_led);
+ ath9k_unregister_led(&priv->rx_led);
+ ath9k_unregister_led(&priv->radio_led);
+}
+
+void ath9k_init_leds(struct ath9k_htc_priv *priv)
+{
+ char *trigger;
+ int ret;
+
+ if (AR_SREV_9287(priv->ah))
+ priv->ah->led_pin = ATH_LED_PIN_9287;
+ else if (AR_SREV_9271(priv->ah))
+ priv->ah->led_pin = ATH_LED_PIN_9271;
+ else if (AR_DEVID_7010(priv->ah))
+ priv->ah->led_pin = ATH_LED_PIN_7010;
+ else
+ priv->ah->led_pin = ATH_LED_PIN_DEF;
+
+ /* Configure gpio 1 for output */
+ ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ /* LED off, active low */
+ ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
+
+ INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work);
+
+ trigger = ieee80211_get_radio_led_name(priv->hw);
+ snprintf(priv->radio_led.name, sizeof(priv->radio_led.name),
+ "ath9k-%s::radio", wiphy_name(priv->hw->wiphy));
+ ret = ath9k_register_led(priv, &priv->radio_led, trigger);
+ priv->radio_led.led_type = ATH_LED_RADIO;
+ if (ret)
+ goto fail;
+
+ trigger = ieee80211_get_assoc_led_name(priv->hw);
+ snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name),
+ "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy));
+ ret = ath9k_register_led(priv, &priv->assoc_led, trigger);
+ priv->assoc_led.led_type = ATH_LED_ASSOC;
+ if (ret)
+ goto fail;
+
+ trigger = ieee80211_get_tx_led_name(priv->hw);
+ snprintf(priv->tx_led.name, sizeof(priv->tx_led.name),
+ "ath9k-%s::tx", wiphy_name(priv->hw->wiphy));
+ ret = ath9k_register_led(priv, &priv->tx_led, trigger);
+ priv->tx_led.led_type = ATH_LED_TX;
+ if (ret)
+ goto fail;
+
+ trigger = ieee80211_get_rx_led_name(priv->hw);
+ snprintf(priv->rx_led.name, sizeof(priv->rx_led.name),
+ "ath9k-%s::rx", wiphy_name(priv->hw->wiphy));
+ ret = ath9k_register_led(priv, &priv->rx_led, trigger);
+ priv->rx_led.led_type = ATH_LED_RX;
+ if (ret)
+ goto fail;
+
+ priv->op_flags &= ~OP_LED_DEINIT;
+
+ return;
+
+fail:
+ cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
+ ath9k_deinit_leds(priv);
+}
+
+/*******************/
+/* Rfkill */
+/*******************/
+
+static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
+{
+ return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
+ priv->ah->rfkill_polarity;
+}
+
+void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
+{
+ struct ath9k_htc_priv *priv = hw->priv;
+ bool blocked = !!ath_is_rfkill_set(priv);
+
+ wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
+}
+
+void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
+{
+ if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ wiphy_rfkill_start_polling(priv->hw->wiphy);
+}
+
+void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
+{
+ struct ath9k_htc_priv *priv = hw->priv;
+ struct ath_hw *ah = priv->ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int ret;
+ u8 cmd_rsp;
+
+ if (!ah->curchan)
+ ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
+
+ /* Reset the HW */
+ ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+ if (ret) {
+ ath_err(common,
+ "Unable to reset hardware; reset status %d (freq %u MHz)\n",
+ ret, ah->curchan->channel);
+ }
+
+ ath_update_txpow(priv);
+
+ /* Start RX */
+ WMI_CMD(WMI_START_RECV_CMDID);
+ ath9k_host_rx_init(priv);
+
+ /* Start TX */
+ htc_start(priv->htc);
+ spin_lock_bh(&priv->tx_lock);
+ priv->tx_queues_stop = false;
+ spin_unlock_bh(&priv->tx_lock);
+ ieee80211_wake_queues(hw);
+
+ WMI_CMD(WMI_ENABLE_INTR_CMDID);
+
+ /* Enable LED */
+ ath9k_hw_cfg_output(ah, ah->led_pin,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ ath9k_hw_set_gpio(ah, ah->led_pin, 0);
+}
+
+void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
+{
+ struct ath9k_htc_priv *priv = hw->priv;
+ struct ath_hw *ah = priv->ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int ret;
+ u8 cmd_rsp;
+
+ ath9k_htc_ps_wakeup(priv);
+
+ /* Disable LED */
+ ath9k_hw_set_gpio(ah, ah->led_pin, 1);
+ ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
+
+ WMI_CMD(WMI_DISABLE_INTR_CMDID);
+
+ /* Stop TX */
+ ieee80211_stop_queues(hw);
+ htc_stop(priv->htc);
+ WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
+ skb_queue_purge(&priv->tx_queue);
+
+ /* Stop RX */
+ WMI_CMD(WMI_STOP_RECV_CMDID);
+
+ /*
+ * The MIB counters have to be disabled here,
+ * since the target doesn't do it.
+ */
+ ath9k_hw_disable_mib_counters(ah);
+
+ if (!ah->curchan)
+ ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
+
+ /* Reset the HW */
+ ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+ if (ret) {
+ ath_err(common,
+ "Unable to reset hardware; reset status %d (freq %u MHz)\n",
+ ret, ah->curchan->channel);
+ }
+
+ /* Disable the PHY */
+ ath9k_hw_phy_disable(ah);
+
+ ath9k_htc_ps_restore(priv);
+ ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
+}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index d54adeb..f4edd72 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -24,7 +24,7 @@ static struct dentry *ath9k_debugfs_root;
/* Utilities */
/*************/
-static void ath_update_txpow(struct ath9k_htc_priv *priv)
+void ath_update_txpow(struct ath9k_htc_priv *priv)
{
struct ath_hw *ah = priv->ah;
@@ -840,317 +840,6 @@ set_timer:
msecs_to_jiffies(cal_interval));
}
-/*******/
-/* LED */
-/*******/
-
-static void ath9k_led_blink_work(struct work_struct *work)
-{
- struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
- ath9k_led_blink_work.work);
-
- if (!(priv->op_flags & OP_LED_ASSOCIATED))
- return;
-
- if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
- (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
- else
- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
- (priv->op_flags & OP_LED_ON) ? 1 : 0);
-
- ieee80211_queue_delayed_work(priv->hw,
- &priv->ath9k_led_blink_work,
- (priv->op_flags & OP_LED_ON) ?
- msecs_to_jiffies(priv->led_off_duration) :
- msecs_to_jiffies(priv->led_on_duration));
-
- priv->led_on_duration = priv->led_on_cnt ?
- max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) :
- ATH_LED_ON_DURATION_IDLE;
- priv->led_off_duration = priv->led_off_cnt ?
- max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) :
- ATH_LED_OFF_DURATION_IDLE;
- priv->led_on_cnt = priv->led_off_cnt = 0;
-
- if (priv->op_flags & OP_LED_ON)
- priv->op_flags &= ~OP_LED_ON;
- else
- priv->op_flags |= OP_LED_ON;
-}
-
-static void ath9k_led_brightness_work(struct work_struct *work)
-{
- struct ath_led *led = container_of(work, struct ath_led,
- brightness_work.work);
- struct ath9k_htc_priv *priv = led->priv;
-
- switch (led->brightness) {
- case LED_OFF:
- if (led->led_type == ATH_LED_ASSOC ||
- led->led_type == ATH_LED_RADIO) {
- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
- (led->led_type == ATH_LED_RADIO));
- priv->op_flags &= ~OP_LED_ASSOCIATED;
- if (led->led_type == ATH_LED_RADIO)
- priv->op_flags &= ~OP_LED_ON;
- } else {
- priv->led_off_cnt++;
- }
- break;
- case LED_FULL:
- if (led->led_type == ATH_LED_ASSOC) {
- priv->op_flags |= OP_LED_ASSOCIATED;
- ieee80211_queue_delayed_work(priv->hw,
- &priv->ath9k_led_blink_work, 0);
- } else if (led->led_type == ATH_LED_RADIO) {
- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
- priv->op_flags |= OP_LED_ON;
- } else {
- priv->led_on_cnt++;
- }
- break;
- default:
- break;
- }
-}
-
-static void ath9k_led_brightness(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
- struct ath9k_htc_priv *priv = led->priv;
-
- led->brightness = brightness;
- if (!(priv->op_flags & OP_LED_DEINIT))
- ieee80211_queue_delayed_work(priv->hw,
- &led->brightness_work, 0);
-}
-
-static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
-{
- cancel_delayed_work_sync(&priv->radio_led.brightness_work);
- cancel_delayed_work_sync(&priv->assoc_led.brightness_work);
- cancel_delayed_work_sync(&priv->tx_led.brightness_work);
- cancel_delayed_work_sync(&priv->rx_led.brightness_work);
-}
-
-static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
- char *trigger)
-{
- int ret;
-
- led->priv = priv;
- led->led_cdev.name = led->name;
- led->led_cdev.default_trigger = trigger;
- led->led_cdev.brightness_set = ath9k_led_brightness;
-
- ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev);
- if (ret)
- ath_err(ath9k_hw_common(priv->ah),
- "Failed to register led:%s", led->name);
- else
- led->registered = 1;
-
- INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
-
- return ret;
-}
-
-static void ath9k_unregister_led(struct ath_led *led)
-{
- if (led->registered) {
- led_classdev_unregister(&led->led_cdev);
- led->registered = 0;
- }
-}
-
-void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
-{
- priv->op_flags |= OP_LED_DEINIT;
- ath9k_unregister_led(&priv->assoc_led);
- priv->op_flags &= ~OP_LED_ASSOCIATED;
- ath9k_unregister_led(&priv->tx_led);
- ath9k_unregister_led(&priv->rx_led);
- ath9k_unregister_led(&priv->radio_led);
-}
-
-void ath9k_init_leds(struct ath9k_htc_priv *priv)
-{
- char *trigger;
- int ret;
-
- if (AR_SREV_9287(priv->ah))
- priv->ah->led_pin = ATH_LED_PIN_9287;
- else if (AR_SREV_9271(priv->ah))
- priv->ah->led_pin = ATH_LED_PIN_9271;
- else if (AR_DEVID_7010(priv->ah))
- priv->ah->led_pin = ATH_LED_PIN_7010;
- else
- priv->ah->led_pin = ATH_LED_PIN_DEF;
-
- /* Configure gpio 1 for output */
- ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
- /* LED off, active low */
- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
-
- INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work);
-
- trigger = ieee80211_get_radio_led_name(priv->hw);
- snprintf(priv->radio_led.name, sizeof(priv->radio_led.name),
- "ath9k-%s::radio", wiphy_name(priv->hw->wiphy));
- ret = ath9k_register_led(priv, &priv->radio_led, trigger);
- priv->radio_led.led_type = ATH_LED_RADIO;
- if (ret)
- goto fail;
-
- trigger = ieee80211_get_assoc_led_name(priv->hw);
- snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name),
- "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy));
- ret = ath9k_register_led(priv, &priv->assoc_led, trigger);
- priv->assoc_led.led_type = ATH_LED_ASSOC;
- if (ret)
- goto fail;
-
- trigger = ieee80211_get_tx_led_name(priv->hw);
- snprintf(priv->tx_led.name, sizeof(priv->tx_led.name),
- "ath9k-%s::tx", wiphy_name(priv->hw->wiphy));
- ret = ath9k_register_led(priv, &priv->tx_led, trigger);
- priv->tx_led.led_type = ATH_LED_TX;
- if (ret)
- goto fail;
-
- trigger = ieee80211_get_rx_led_name(priv->hw);
- snprintf(priv->rx_led.name, sizeof(priv->rx_led.name),
- "ath9k-%s::rx", wiphy_name(priv->hw->wiphy));
- ret = ath9k_register_led(priv, &priv->rx_led, trigger);
- priv->rx_led.led_type = ATH_LED_RX;
- if (ret)
- goto fail;
-
- priv->op_flags &= ~OP_LED_DEINIT;
-
- return;
-
-fail:
- cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
- ath9k_deinit_leds(priv);
-}
-
-/*******************/
-/* Rfkill */
-/*******************/
-
-static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
-{
- return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
- priv->ah->rfkill_polarity;
-}
-
-static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
-{
- struct ath9k_htc_priv *priv = hw->priv;
- bool blocked = !!ath_is_rfkill_set(priv);
-
- wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
-}
-
-void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
-{
- if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
- wiphy_rfkill_start_polling(priv->hw->wiphy);
-}
-
-static void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
-{
- struct ath9k_htc_priv *priv = hw->priv;
- struct ath_hw *ah = priv->ah;
- struct ath_common *common = ath9k_hw_common(ah);
- int ret;
- u8 cmd_rsp;
-
- if (!ah->curchan)
- ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-
- /* Reset the HW */
- ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
- if (ret) {
- ath_err(common,
- "Unable to reset hardware; reset status %d (freq %u MHz)\n",
- ret, ah->curchan->channel);
- }
-
- ath_update_txpow(priv);
-
- /* Start RX */
- WMI_CMD(WMI_START_RECV_CMDID);
- ath9k_host_rx_init(priv);
-
- /* Start TX */
- htc_start(priv->htc);
- spin_lock_bh(&priv->tx_lock);
- priv->tx_queues_stop = false;
- spin_unlock_bh(&priv->tx_lock);
- ieee80211_wake_queues(hw);
-
- WMI_CMD(WMI_ENABLE_INTR_CMDID);
-
- /* Enable LED */
- ath9k_hw_cfg_output(ah, ah->led_pin,
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
- ath9k_hw_set_gpio(ah, ah->led_pin, 0);
-}
-
-static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
-{
- struct ath9k_htc_priv *priv = hw->priv;
- struct ath_hw *ah = priv->ah;
- struct ath_common *common = ath9k_hw_common(ah);
- int ret;
- u8 cmd_rsp;
-
- ath9k_htc_ps_wakeup(priv);
-
- /* Disable LED */
- ath9k_hw_set_gpio(ah, ah->led_pin, 1);
- ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
-
- WMI_CMD(WMI_DISABLE_INTR_CMDID);
-
- /* Stop TX */
- ieee80211_stop_queues(hw);
- htc_stop(priv->htc);
- WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
- skb_queue_purge(&priv->tx_queue);
-
- /* Stop RX */
- WMI_CMD(WMI_STOP_RECV_CMDID);
-
- /*
- * The MIB counters have to be disabled here,
- * since the target doesn't do it.
- */
- ath9k_hw_disable_mib_counters(ah);
-
- if (!ah->curchan)
- ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-
- /* Reset the HW */
- ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
- if (ret) {
- ath_err(common,
- "Unable to reset hardware; reset status %d (freq %u MHz)\n",
- ret, ah->curchan->channel);
- }
-
- /* Disable the PHY */
- ath9k_hw_phy_disable(ah);
-
- ath9k_htc_ps_restore(priv);
- ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
-}
-
/**********************/
/* mac80211 Callbacks */
/**********************/
--
1.7.3.4
^ permalink raw reply related
* Re: [PATCH 3/5] ath9k_htc: Handle FATAL events
From: Vasanthakumar Thiagarajan @ 2010-12-28 8:23 UTC (permalink / raw)
To: Sujith
Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
Sujith Manoharan
In-Reply-To: <19737.39891.227133.163154@gargle.gargle.HOWL>
On Tue, Dec 28, 2010 at 01:42:03PM +0530, Sujith wrote:
> From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
>
> The device has to be reset when a FATAL event is received.
> Not doing so would leave the card in a non-working state.
>
> Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
> ---
> drivers/net/wireless/ath/ath9k/htc.h | 6 ++-
> drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 ++-
> drivers/net/wireless/ath/ath9k/htc_drv_main.c | 57 ++++++++++++++++++++++++-
> drivers/net/wireless/ath/ath9k/wmi.c | 18 +++++++-
> drivers/net/wireless/ath/ath9k/wmi.h | 3 +-
> 5 files changed, 84 insertions(+), 8 deletions(-)
>
> +void ath9k_htc_reset(struct ath9k_htc_priv *priv)
> +{
> + struct ath_hw *ah = priv->ah;
> + struct ath_common *common = ath9k_hw_common(ah);
> + struct ieee80211_channel *channel = priv->hw->conf.channel;
> + struct ath9k_hw_cal_data *caldata;
> + enum htc_phymode mode;
> + __be16 htc_mode;
> + u8 cmd_rsp;
> + int ret;
> +
> + mutex_lock(&priv->mutex);
This will result in a deadlock with the one in ath9k_htc_stop().
Vasanth
^ permalink raw reply
* Re: [PATCH v2 06/18] wl1271: AP mode - init sequence
From: Luciano Coelho @ 2010-12-28 8:34 UTC (permalink / raw)
To: ext Arik Nemtsov; +Cc: linux-wireless
In-Reply-To: <AANLkTikrgQwxBKSc_s-DHU+ktU+HwHb1hBukL+0rgpYK@mail.gmail.com>
On Tue, 2010-12-28 at 08:16 +0200, ext Arik Nemtsov wrote:
> >> diff --git a/drivers/net/wireless/wl12xx/init.h
> b/drivers/net/wireless/wl12xx/init.h
> >> index 7762421..4d37210 100644
> >> --- a/drivers/net/wireless/wl12xx/init.h
> >> +++ b/drivers/net/wireless/wl12xx/init.h
> >> @@ -27,10 +27,13 @@
> >> #include "wl12xx.h"
> >>
> >> int wl1271_hw_init_power_auth(struct wl1271 *wl);
> >> -int wl1271_init_templates_config(struct wl1271 *wl);
> >> +int wl1271_sta_init_templates_config(struct wl1271 *wl);
> >> int wl1271_init_phy_config(struct wl1271 *wl);
> >> int wl1271_init_pta(struct wl1271 *wl);
> >> int wl1271_init_energy_detection(struct wl1271 *wl);
> >> int wl1271_hw_init(struct wl1271 *wl);
> >>
> >> +/* Functions from wl1271_main.c */
> >> +u32 wl1271_min_rate_get(struct wl1271 *wl);
> >> +
> >
> > This is bad and shouldn't be here. Need to find a better place for
> it.
>
> How about tx.h? It's TX rate we're talking about here after all.
> I can also change the name to wl1271_tx_min_rate_get().
Sounds good.
--
Cheers,
Luca.
^ permalink raw reply
* Re: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Johannes Berg @ 2010-12-28 8:38 UTC (permalink / raw)
To: Bruno Randolf; +Cc: linville, linux-wireless, mcgrof
In-Reply-To: <201012281431.46536.br1@einfach.org>
On Tue, 2010-12-28 at 14:31 +0900, Bruno Randolf wrote:
> > > - if (freq == ieee80211_channel_to_frequency(12) ||
> > > - freq == ieee80211_channel_to_frequency(13) ||
> > > - freq == ieee80211_channel_to_frequency(14))
> > > + if (freq == ieee80211_channel_to_frequency(12, IEEE80211_BAND_2GHZ) ||
> > > + freq == ieee80211_channel_to_frequency(13, IEEE80211_BAND_2GHZ) ||
> > > + freq == ieee80211_channel_to_frequency(14, IEEE80211_BAND_2GHZ))
> > >
> > > return true;
> >
> > This seems strange ... why not just hardcode the values??
>
> True, but this is not my code, I just did the change for the new function
> parameter. It's in net/wireless/reg.c, so I'll CC: Luis.
Right. It seems rather complicated though, especially with this change.
> Any other comments on the code or purpose of this patch?
Not really. I guess it seems fine. Do you know if there are ever any
starting values used other than 4900 and 5000?
johannes
^ permalink raw reply
* Patches submitted should apply to which git repository?
From: Naveenan @ 2010-12-28 8:40 UTC (permalink / raw)
To: linux-wireless
Hi,
I would like to submit a patch to linux-wireless and was wondering
what git repository should my patch be apply-able to so that there
wouldn't be any merge conflicts?
I went through:
http://wireless.kernel.org/en/developers/Documentation/SubmittingPatches
but couldn't find this information there so was hoping someone could
point the exact git repository. My current patch applies to
wireless-testing but doesn't apply to wireless-2.6 (due to a trivial
merge conflict) . The changes I'm making are to mac80211.
Thanks.
^ permalink raw reply
* Re: [PATCH 3/5] ath9k_htc: Handle FATAL events
From: Sujith @ 2010-12-28 8:48 UTC (permalink / raw)
To: Vasanthakumar Thiagarajan
Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
Sujith Manoharan
In-Reply-To: <20101228082356.GB31274@vasanth-laptop>
Vasanthakumar Thiagarajan wrote:
> On Tue, Dec 28, 2010 at 01:42:03PM +0530, Sujith wrote:
> > From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
> >
> > The device has to be reset when a FATAL event is received.
> > Not doing so would leave the card in a non-working state.
> >
> > Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
> > ---
> > drivers/net/wireless/ath/ath9k/htc.h | 6 ++-
> > drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 ++-
> > drivers/net/wireless/ath/ath9k/htc_drv_main.c | 57 ++++++++++++++++++++++++-
> > drivers/net/wireless/ath/ath9k/wmi.c | 18 +++++++-
> > drivers/net/wireless/ath/ath9k/wmi.h | 3 +-
> > 5 files changed, 84 insertions(+), 8 deletions(-)
> >
> > +void ath9k_htc_reset(struct ath9k_htc_priv *priv)
> > +{
> > + struct ath_hw *ah = priv->ah;
> > + struct ath_common *common = ath9k_hw_common(ah);
> > + struct ieee80211_channel *channel = priv->hw->conf.channel;
> > + struct ath9k_hw_cal_data *caldata;
> > + enum htc_phymode mode;
> > + __be16 htc_mode;
> > + u8 cmd_rsp;
> > + int ret;
> > +
> > + mutex_lock(&priv->mutex);
>
> This will result in a deadlock with the one in ath9k_htc_stop().
Indeed yes, nice catch.
There is no need to lock the cancellation stuff anyway,
I'll just move them outside the lock.
Thanks for the review.
Sujith
^ permalink raw reply
* Re: Patches submitted should apply to which git repository?
From: Johannes Berg @ 2010-12-28 8:51 UTC (permalink / raw)
To: Naveenan; +Cc: linux-wireless
In-Reply-To: <AANLkTi=MhYzv54WvEwYGh15KC4LHyM=EVd-s+1BG8pBT@mail.gmail.com>
On Tue, 2010-12-28 at 02:40 -0600, Naveenan wrote:
> Hi,
> I would like to submit a patch to linux-wireless and was wondering
> what git repository should my patch be apply-able to so that there
> wouldn't be any merge conflicts?
>
> I went through:
> http://wireless.kernel.org/en/developers/Documentation/SubmittingPatches
> but couldn't find this information there so was hoping someone could
> point the exact git repository. My current patch applies to
> wireless-testing but doesn't apply to wireless-2.6 (due to a trivial
> merge conflict) . The changes I'm making are to mac80211.
If they're fixes and required in wireless-2.6, then you should make them
apply there, but ask yourself if they really need to be there. If not,
you can typically just submit them on top of wireless-testing, although
they will have to be applied to wireless-next-2.6.
johannes
^ permalink raw reply
* [PATCH v2 1/6] ath9k_htc: Fix warning on device removal
From: Sujith @ 2010-12-28 8:57 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Sujith.Manoharan
From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
The commit "ath9k_hw: warn if we cannot change the power to the chip"
introduced a new warning to indicate chip powerup failures, but this
is not required for devices that have been removed. Handle USB device
removal properly by checking for unplugged status.
For PCI devices, this warning will still be seen when the card is pulled
out, not sure how to check for card removal.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/eeprom.h | 2 --
drivers/net/wireless/ath/ath9k/hif_usb.c | 6 +++---
drivers/net/wireless/ath/ath9k/htc.h | 5 ++---
drivers/net/wireless/ath/ath9k/htc_drv_init.c | 5 +----
drivers/net/wireless/ath/ath9k/hw.c | 4 +++-
drivers/net/wireless/ath/ath9k/hw.h | 4 ++++
drivers/net/wireless/ath/ath9k/wmi.c | 2 +-
7 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index f6f09d1..58e2ddc 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -23,8 +23,6 @@
#include <net/cfg80211.h>
#include "ar9003_eeprom.h"
-#define AH_USE_EEPROM 0x1
-
#ifdef __BIG_ENDIAN
#define AR5416_EEPROM_MAGIC 0x5aa5
#else
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 22b68b3..c20c8c8 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -993,16 +993,16 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
+ bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false;
if (hif_dev) {
- ath9k_htc_hw_deinit(hif_dev->htc_handle,
- (udev->state == USB_STATE_NOTATTACHED) ? true : false);
+ ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
ath9k_htc_hw_free(hif_dev->htc_handle);
ath9k_hif_usb_dev_deinit(hif_dev);
usb_set_intfdata(interface, NULL);
}
- if (hif_dev->flags & HIF_USB_START)
+ if (!unplugged && (hif_dev->flags & HIF_USB_START))
ath9k_hif_usb_reboot(udev);
kfree(hif_dev);
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index fdf9d5f..e6c2f0a 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -339,9 +339,8 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv);
#define OP_ASSOCIATED BIT(7)
#define OP_ENABLE_BEACON BIT(8)
#define OP_LED_DEINIT BIT(9)
-#define OP_UNPLUGGED BIT(10)
-#define OP_BT_PRIORITY_DETECTED BIT(11)
-#define OP_BT_SCAN BIT(12)
+#define OP_BT_PRIORITY_DETECTED BIT(10)
+#define OP_BT_SCAN BIT(11)
struct ath9k_htc_priv {
struct device *dev;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 0f6be35..724f545 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -851,9 +851,6 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
if (ret)
goto err_init;
- /* The device may have been unplugged earlier. */
- priv->op_flags &= ~OP_UNPLUGGED;
-
ret = ath9k_init_device(priv, devid, product, drv_info);
if (ret)
goto err_init;
@@ -873,7 +870,7 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
/* Check if the device has been yanked out. */
if (hotunplug)
- htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
+ htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
ath9k_deinit_device(htc_handle->drv_priv);
ath9k_deinit_wmi(htc_handle->drv_priv);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 4b51ed4..fde9786 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1615,7 +1615,9 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
* simply keep the ATH_DBG_WARN_ON_ONCE() but make
* ath9k_hw_setpower() return type void.
*/
- ATH_DBG_WARN_ON_ONCE(!status);
+
+ if (!(ah->ah_flags & AH_UNPLUGGED))
+ ATH_DBG_WARN_ON_ONCE(!status);
return status;
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index b8ffaa5..5a3dfec 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -646,6 +646,10 @@ struct ath_nf_limits {
s16 nominal;
};
+/* ah_flags */
+#define AH_USE_EEPROM 0x1
+#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
+
struct ath_hw {
struct ieee80211_hw *hw;
struct ath_common common;
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 8f42ea7..573daca 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -250,7 +250,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
int time_left, ret = 0;
unsigned long flags;
- if (wmi->drv_priv->op_flags & OP_UNPLUGGED)
+ if (ah->ah_flags & AH_UNPLUGGED)
return 0;
skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC);
--
1.7.3.4
^ permalink raw reply related
* [PATCH v2 2/6] ath9k_htc: Handle pending URBs properly
From: Sujith @ 2010-12-28 8:58 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Sujith.Manoharan
From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
When doing a channel change, the pending URBs have to be killed
properly on calling htc_stop().
This fixes the probe response timeout seen when sending UDP traffic at
a high rate and running background scan at the same time.
Cc: stable <stable@kernel.org>
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/hif_usb.c | 40 +++++++++++++++++++++++++++---
drivers/net/wireless/ath/ath9k/hif_usb.h | 1 +
2 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index c20c8c8..5ab3084 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -153,16 +153,36 @@ static void hif_usb_tx_cb(struct urb *urb)
case -ENODEV:
case -ESHUTDOWN:
/*
- * The URB has been killed, free the SKBs
- * and return.
+ * The URB has been killed, free the SKBs.
*/
ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
- return;
+
+ /*
+ * If the URBs are being flushed, no need to add this
+ * URB to the free list.
+ */
+ spin_lock(&hif_dev->tx.tx_lock);
+ if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
+ spin_unlock(&hif_dev->tx.tx_lock);
+ return;
+ }
+ spin_unlock(&hif_dev->tx.tx_lock);
+
+ /*
+ * In the stop() case, this URB has to be added to
+ * the free list.
+ */
+ goto add_free;
default:
break;
}
- /* Check if TX has been stopped */
+ /*
+ * Check if TX has been stopped, this is needed because
+ * this CB could have been invoked just after the TX lock
+ * was released in hif_stop() and kill_urb() hasn't been
+ * called yet.
+ */
spin_lock(&hif_dev->tx.tx_lock);
if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
spin_unlock(&hif_dev->tx.tx_lock);
@@ -314,6 +334,7 @@ static void hif_usb_start(void *hif_handle, u8 pipe_id)
static void hif_usb_stop(void *hif_handle, u8 pipe_id)
{
struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
+ struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
unsigned long flags;
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
@@ -321,6 +342,12 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id)
hif_dev->tx.tx_skb_cnt = 0;
hif_dev->tx.flags |= HIF_USB_TX_STOP;
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
+
+ /* The pending URBs have to be canceled. */
+ list_for_each_entry_safe(tx_buf, tx_buf_tmp,
+ &hif_dev->tx.tx_pending, list) {
+ usb_kill_urb(tx_buf->urb);
+ }
}
static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
@@ -587,6 +614,7 @@ free:
static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
{
struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
+ unsigned long flags;
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
&hif_dev->tx.tx_buf, list) {
@@ -597,6 +625,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
kfree(tx_buf);
}
+ spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
+ hif_dev->tx.flags |= HIF_USB_TX_FLUSH;
+ spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
+
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
&hif_dev->tx.tx_pending, list) {
usb_kill_urb(tx_buf->urb);
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index e4a5e2e..7b9d863 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -64,6 +64,7 @@ struct tx_buf {
};
#define HIF_USB_TX_STOP BIT(0)
+#define HIF_USB_TX_FLUSH BIT(1)
struct hif_usb_tx {
u8 flags;
--
1.7.3.4
^ permalink raw reply related
* [PATCH v2 3/6] ath9k_htc: Move work cancellation outside of mutex
From: Sujith @ 2010-12-28 8:58 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Sujith.Manoharan
From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
There is no need to lock the various work cancellation
calls. This will be helpful when handling FATAL events.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index dd17909..5f75f70 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1218,6 +1218,11 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
int ret = 0;
u8 cmd_rsp;
+ /* Cancel all the running timers/work .. */
+ cancel_work_sync(&priv->ps_work);
+ cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
+ ath9k_led_stop_brightness(priv);
+
mutex_lock(&priv->mutex);
if (priv->op_flags & OP_INVALID) {
@@ -1226,11 +1231,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
return;
}
- /* Cancel all the running timers/work .. */
- cancel_work_sync(&priv->ps_work);
- cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
- ath9k_led_stop_brightness(priv);
-
ath9k_htc_ps_wakeup(priv);
htc_stop(priv->htc);
WMI_CMD(WMI_DISABLE_INTR_CMDID);
--
1.7.3.4
^ permalink raw reply related
* [PATCH v2 4/6] ath9k_htc: Handle FATAL events
From: Sujith @ 2010-12-28 8:58 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Sujith.Manoharan
From: Sujith Manoharan <Sujith.Manoharan@atheros.com>
The device has to be reset when a FATAL event is received.
Not doing so would leave the card in a non-working state.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/htc.h | 6 ++-
drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 ++-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 57 ++++++++++++++++++++++++-
drivers/net/wireless/ath/ath9k/wmi.c | 18 +++++++-
drivers/net/wireless/ath/ath9k/wmi.h | 3 +-
5 files changed, 84 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index e6c2f0a..1062274 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -377,7 +377,7 @@ struct ath9k_htc_priv {
struct ieee80211_vif *vif;
struct htc_beacon_config cur_beacon_conf;
unsigned int rxfilter;
- struct tasklet_struct wmi_tasklet;
+ struct tasklet_struct swba_tasklet;
struct tasklet_struct rx_tasklet;
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
struct ath9k_htc_rx rx;
@@ -385,6 +385,7 @@ struct ath9k_htc_priv {
struct sk_buff_head tx_queue;
struct delayed_work ath9k_ani_work;
struct work_struct ps_work;
+ struct work_struct fatal_work;
struct mutex htc_pm_lock;
unsigned long ps_usecount;
@@ -419,6 +420,8 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
common->bus_ops->read_cachesize(common, csz);
}
+void ath9k_htc_reset(struct ath9k_htc_priv *priv);
+
void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif);
@@ -434,6 +437,7 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
void ath9k_htc_station_work(struct work_struct *work);
void ath9k_htc_aggr_work(struct work_struct *work);
void ath9k_ani_work(struct work_struct *work);;
+void ath_start_ani(struct ath9k_htc_priv *priv);
int ath9k_tx_init(struct ath9k_htc_priv *priv);
void ath9k_tx_tasklet(unsigned long data);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 724f545..9150ca6 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -142,7 +142,7 @@ static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
{
ath9k_htc_exit_debug(priv->ah);
ath9k_hw_deinit(priv->ah);
- tasklet_kill(&priv->wmi_tasklet);
+ tasklet_kill(&priv->swba_tasklet);
tasklet_kill(&priv->rx_tasklet);
tasklet_kill(&priv->tx_tasklet);
kfree(priv->ah);
@@ -647,13 +647,15 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
spin_lock_init(&priv->tx_lock);
mutex_init(&priv->mutex);
mutex_init(&priv->htc_pm_lock);
- tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
+ tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet,
(unsigned long)priv);
tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
(unsigned long)priv);
- tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
+ tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
+ (unsigned long)priv);
INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
INIT_WORK(&priv->ps_work, ath9k_ps_work);
+ INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
/*
* Cache line size is used to size and align various
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 5f75f70..07f10dd 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -116,6 +116,60 @@ void ath9k_ps_work(struct work_struct *work)
ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
}
+void ath9k_htc_reset(struct ath9k_htc_priv *priv)
+{
+ struct ath_hw *ah = priv->ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_channel *channel = priv->hw->conf.channel;
+ struct ath9k_hw_cal_data *caldata;
+ enum htc_phymode mode;
+ __be16 htc_mode;
+ u8 cmd_rsp;
+ int ret;
+
+ mutex_lock(&priv->mutex);
+ ath9k_htc_ps_wakeup(priv);
+
+ if (priv->op_flags & OP_ASSOCIATED)
+ cancel_delayed_work_sync(&priv->ath9k_ani_work);
+
+ ieee80211_stop_queues(priv->hw);
+ htc_stop(priv->htc);
+ WMI_CMD(WMI_DISABLE_INTR_CMDID);
+ WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
+ WMI_CMD(WMI_STOP_RECV_CMDID);
+
+ caldata = &priv->caldata[channel->hw_value];
+ ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
+ if (ret) {
+ ath_err(common,
+ "Unable to reset device (%u Mhz) reset status %d\n",
+ channel->center_freq, ret);
+ }
+
+ ath_update_txpow(priv);
+
+ WMI_CMD(WMI_START_RECV_CMDID);
+ ath9k_host_rx_init(priv);
+
+ mode = ath9k_htc_get_curmode(priv, ah->curchan);
+ htc_mode = cpu_to_be16(mode);
+ WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
+
+ WMI_CMD(WMI_ENABLE_INTR_CMDID);
+ htc_start(priv->htc);
+
+ if (priv->op_flags & OP_ASSOCIATED) {
+ ath9k_htc_beacon_config(priv, priv->vif);
+ ath_start_ani(priv);
+ }
+
+ ieee80211_wake_queues(priv->hw);
+
+ ath9k_htc_ps_restore(priv);
+ mutex_unlock(&priv->mutex);
+}
+
static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
struct ieee80211_hw *hw,
struct ath9k_channel *hchan)
@@ -690,7 +744,7 @@ void ath9k_htc_debug_remove_root(void)
/* ANI */
/*******/
-static void ath_start_ani(struct ath9k_htc_priv *priv)
+void ath_start_ani(struct ath9k_htc_priv *priv)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -1219,6 +1273,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
u8 cmd_rsp;
/* Cancel all the running timers/work .. */
+ cancel_work_sync(&priv->fatal_work);
cancel_work_sync(&priv->ps_work);
cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
ath9k_led_stop_brightness(priv);
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 573daca..dc862f5 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -120,7 +120,7 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
kfree(priv->wmi);
}
-void ath9k_wmi_tasklet(unsigned long data)
+void ath9k_swba_tasklet(unsigned long data)
{
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -131,6 +131,16 @@ void ath9k_wmi_tasklet(unsigned long data)
}
+void ath9k_fatal_work(struct work_struct *work)
+{
+ struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+ fatal_work);
+ struct ath_common *common = ath9k_hw_common(priv->ah);
+
+ ath_dbg(common, ATH_DBG_FATAL, "FATAL Event received, resetting device\n");
+ ath9k_htc_reset(priv);
+}
+
static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb)
{
skb_pull(skb, sizeof(struct wmi_cmd_hdr));
@@ -163,7 +173,11 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
switch (cmd_id) {
case WMI_SWBA_EVENTID:
wmi->beacon_pending = *(u8 *)wmi_event;
- tasklet_schedule(&wmi->drv_priv->wmi_tasklet);
+ tasklet_schedule(&wmi->drv_priv->swba_tasklet);
+ break;
+ case WMI_FATAL_EVENTID:
+ ieee80211_queue_work(wmi->drv_priv->hw,
+ &wmi->drv_priv->fatal_work);
break;
case WMI_TXRATE_EVENTID:
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h
index ac61074..4208427 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.h
+++ b/drivers/net/wireless/ath/ath9k/wmi.h
@@ -117,7 +117,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
u8 *cmd_buf, u32 cmd_len,
u8 *rsp_buf, u32 rsp_len,
u32 timeout);
-void ath9k_wmi_tasklet(unsigned long data);
+void ath9k_swba_tasklet(unsigned long data);
+void ath9k_fatal_work(struct work_struct *work);
#define WMI_CMD(_wmi_cmd) \
do { \
--
1.7.3.4
^ 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