* Re: [PATCH v2] brcmsmac: Further reduce log spam from tx phy messages
From: Arend van Spriel @ 2013-07-15 16:26 UTC (permalink / raw)
To: John Greene; +Cc: linville, linux-wireless
In-Reply-To: <1373895092-27057-1-git-send-email-jogreene@redhat.com>
On 07/15/13 15:31, John Greene wrote:
> Relegate 2 phy messages to debug status as they create excessive
> log spam, noted in multiple bugzillas for brcmsmac v3.8 and up.
> This is a follow on to net-next 99e94940697adec4f84758adb2db71f4a82c7ba5:
> brcmsmac: Reduce log spam in heavy tx, make err print in debug
>
> brcmsmac bcma0:0: phyerr 0x10, rate 0x14
> brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete:
> ampdu tx phy error (0x10)
Hi John,
Thanks for the patch. Still trying to find where these are coming from,
but we seem to have slight variation of this device not showing this.
> ver 2: Two trivial whitespace fixes.
this kind of info recommended to be placed under the signed-off line so
it does not end up in the git log. Apart from that you can add my ack.
Acked-by: Arend van Spriel <arend@broadcom.com>
> Signed-off-by: John Greene<jogreene@redhat.com>
> ---
so here
---
> drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +++---
> drivers/net/wireless/brcm80211/brcmsmac/main.c | 4 ++--
> 2 files changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
> index bd98285..fa391e4 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
> @@ -928,9 +928,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
> }
> } else if (txs->phyerr) {
> update_rate = false;
> - brcms_err(wlc->hw->d11core,
> - "%s: ampdu tx phy error (0x%x)\n",
> - __func__, txs->phyerr);
> + brcms_dbg_ht(wlc->hw->d11core,
> + "%s: ampdu tx phy error (0x%x)\n",
> + __func__, txs->phyerr);
> }
> }
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> index 9fd6f2f..7ca10bf 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> @@ -882,8 +882,8 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
> mcl = le16_to_cpu(txh->MacTxControlLow);
>
> if (txs->phyerr)
> - brcms_err(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
> - txs->phyerr, txh->MainRates);
> + brcms_dbg_tx(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
> + txs->phyerr, txh->MainRates);
>
> if (txs->frameid != le16_to_cpu(txh->TxFrameID)) {
> brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n");
^ permalink raw reply
* Re: [PATCH v2] brcmsmac: Further reduce log spam from tx phy messages
From: John Greene @ 2013-07-15 17:26 UTC (permalink / raw)
To: Arend van Spriel; +Cc: linville, linux-wireless
In-Reply-To: <51E4229A.5070803@broadcom.com>
On 07/15/2013 12:26 PM, Arend van Spriel wrote:
> On 07/15/13 15:31, John Greene wrote:
>> Relegate 2 phy messages to debug status as they create excessive
>> log spam, noted in multiple bugzillas for brcmsmac v3.8 and up.
>> This is a follow on to net-next 99e94940697adec4f84758adb2db71f4a82c7ba5:
>> brcmsmac: Reduce log spam in heavy tx, make err print in debug
>>
>> brcmsmac bcma0:0: phyerr 0x10, rate 0x14
>> brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete:
>> ampdu tx phy error (0x10)
>
> Hi John,
>
> Thanks for the patch. Still trying to find where these are coming from,
> but we seem to have slight variation of this device not showing this.
>
>> ver 2: Two trivial whitespace fixes.
>
> this kind of info recommended to be placed under the signed-off line so
> it does not end up in the git log. Apart from that you can add my ack.
>
> Acked-by: Arend van Spriel <arend@broadcom.com>
>> Signed-off-by: John Greene<jogreene@redhat.com>
>> ---
> so here
> ---
>> drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +++---
>> drivers/net/wireless/brcm80211/brcmsmac/main.c | 4 ++--
>> 2 files changed, 5 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
>> b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
>> index bd98285..fa391e4 100644
>> --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
>> +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
>> @@ -928,9 +928,9 @@ brcms_c_ampdu_dotxstatus_complete(struct
>> ampdu_info *ampdu, struct scb *scb,
>> }
>> } else if (txs->phyerr) {
>> update_rate = false;
>> - brcms_err(wlc->hw->d11core,
>> - "%s: ampdu tx phy error (0x%x)\n",
>> - __func__, txs->phyerr);
>> + brcms_dbg_ht(wlc->hw->d11core,
>> + "%s: ampdu tx phy error (0x%x)\n",
>> + __func__, txs->phyerr);
>> }
>> }
>>
>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> index 9fd6f2f..7ca10bf 100644
>> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
>> @@ -882,8 +882,8 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc,
>> struct tx_status *txs)
>> mcl = le16_to_cpu(txh->MacTxControlLow);
>>
>> if (txs->phyerr)
>> - brcms_err(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
>> - txs->phyerr, txh->MainRates);
>> + brcms_dbg_tx(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
>> + txs->phyerr, txh->MainRates);
>>
>> if (txs->frameid != le16_to_cpu(txh->TxFrameID)) {
>> brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n");
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Thanks Arend. Look forward to hearing about root cause. From what I've
seen, it's not a low signal issue: users have strong signal (>-60) but
PHY is reporting errors because the rate fallback exhausted rates list?
Anything I can do to gather info from users? Have some willing users.
Third time the charm for this patch. It's Monday. v3 on the way.
--
John Greene
^ permalink raw reply
* [PATCH v3] brcmsmac: Further reduce log spam from tx phy messages
From: John Greene @ 2013-07-15 17:30 UTC (permalink / raw)
To: linville; +Cc: arend, linux-wireless
Relegate 2 phy messages to debug status as they create excessive
log spam, noted in multiple bugzillas for brcmsmac v3.8 and up.
This is a follow on to net-next 99e94940697adec4f84758adb2db71f4a82c7ba5:
brcmsmac: Reduce log spam in heavy tx, make err print in debug
brcmsmac bcma0:0: phyerr 0x10, rate 0x14
brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete:
ampdu tx phy error (0x10)
Signed-off-by: John Greene <jogreene@redhat.com>
ver 2: Two trivial whitespace fixes.
ver 3: My ver 2 comment in wrong place.
---
drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +++---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index bd98285..fa391e4 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -928,9 +928,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
}
} else if (txs->phyerr) {
update_rate = false;
- brcms_err(wlc->hw->d11core,
- "%s: ampdu tx phy error (0x%x)\n",
- __func__, txs->phyerr);
+ brcms_dbg_ht(wlc->hw->d11core,
+ "%s: ampdu tx phy error (0x%x)\n",
+ __func__, txs->phyerr);
}
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 9fd6f2f..7ca10bf 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -882,8 +882,8 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
mcl = le16_to_cpu(txh->MacTxControlLow);
if (txs->phyerr)
- brcms_err(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
- txs->phyerr, txh->MainRates);
+ brcms_dbg_tx(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
+ txs->phyerr, txh->MainRates);
if (txs->frameid != le16_to_cpu(txh->TxFrameID)) {
brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n");
--
1.7.11.7
^ permalink raw reply related
* Re: [PATCH 3.11] mac80211/minstrel: fix NULL pointer dereference issue
From: Krzysztof Mazur @ 2013-07-15 17:32 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless, johannes
In-Reply-To: <1373891706-1071-1-git-send-email-nbd@openwrt.org>
On Mon, Jul 15, 2013 at 02:35:06PM +0200, Felix Fietkau wrote:
> When priv_sta == NULL, mi->prev_sample is dereferenced too early. Move
> the assignment further down, after the rate_control_send_low call.
>
> Reported-by: Krzysztof Mazur <krzysiek@podlesie.net>
> Cc: stable@vger.kernel.org # 3.10
> Signed-off-by: Felix Fietkau <nbd@openwrt.org>
> ---
> net/mac80211/rc80211_minstrel.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
Works for me.
Thanks,
Krzysiek
^ permalink raw reply
* Re: [PATCH v3] brcmsmac: Further reduce log spam from tx phy messages
From: John W. Linville @ 2013-07-15 17:55 UTC (permalink / raw)
To: John Greene; +Cc: arend, linux-wireless
In-Reply-To: <1373909435-29811-1-git-send-email-jogreene@redhat.com>
On Mon, Jul 15, 2013 at 01:30:35PM -0400, John Greene wrote:
> Relegate 2 phy messages to debug status as they create excessive
> log spam, noted in multiple bugzillas for brcmsmac v3.8 and up.
> This is a follow on to net-next 99e94940697adec4f84758adb2db71f4a82c7ba5:
> brcmsmac: Reduce log spam in heavy tx, make err print in debug
>
> brcmsmac bcma0:0: phyerr 0x10, rate 0x14
> brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete:
> ampdu tx phy error (0x10)
>
> Signed-off-by: John Greene <jogreene@redhat.com>
>
> ver 2: Two trivial whitespace fixes.
> ver 3: My ver 2 comment in wrong place.
These lines...
> ---
Should go here, after the "---" line...
> drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +++---
> drivers/net/wireless/brcm80211/brcmsmac/main.c | 4 ++--
> 2 files changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
> index bd98285..fa391e4 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
> @@ -928,9 +928,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
> }
> } else if (txs->phyerr) {
> update_rate = false;
> - brcms_err(wlc->hw->d11core,
> - "%s: ampdu tx phy error (0x%x)\n",
> - __func__, txs->phyerr);
> + brcms_dbg_ht(wlc->hw->d11core,
> + "%s: ampdu tx phy error (0x%x)\n",
> + __func__, txs->phyerr);
> }
> }
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> index 9fd6f2f..7ca10bf 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> @@ -882,8 +882,8 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
> mcl = le16_to_cpu(txh->MacTxControlLow);
>
> if (txs->phyerr)
> - brcms_err(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
> - txs->phyerr, txh->MainRates);
> + brcms_dbg_tx(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
> + txs->phyerr, txh->MainRates);
>
> if (txs->frameid != le16_to_cpu(txh->TxFrameID)) {
> brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n");
> --
> 1.7.11.7
>
>
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* [PATCH v4] brcmsmac: Further reduce log spam from tx phy messages
From: John Greene @ 2013-07-15 18:33 UTC (permalink / raw)
To: linville; +Cc: arend, linux-wireless
Relegate 2 phy messages to debug status as they create excessive
log spam, noted in multiple bugzillas for brcmsmac v3.8 and up.
This is a follow on to net-next 99e94940697adec4f84758adb2db71f4a82c7ba5:
brcmsmac: Reduce log spam in heavy tx, make err print in debug
brcmsmac bcma0:0: phyerr 0x10, rate 0x14
brcmsmac bcma0:0: brcms_c_ampdu_dotxstatus_complete:
ampdu tx phy error (0x10)
Signed-off-by: John Greene <jogreene@redhat.com>
---
ver 2: Two trivial whitespace fixes.
ver 3: My ver 2 comment in wrong place.
ver 4: Missing --- above version block here
---
drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +++---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index bd98285..fa391e4 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -928,9 +928,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
}
} else if (txs->phyerr) {
update_rate = false;
- brcms_err(wlc->hw->d11core,
- "%s: ampdu tx phy error (0x%x)\n",
- __func__, txs->phyerr);
+ brcms_dbg_ht(wlc->hw->d11core,
+ "%s: ampdu tx phy error (0x%x)\n",
+ __func__, txs->phyerr);
}
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 9fd6f2f..7ca10bf 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -882,8 +882,8 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
mcl = le16_to_cpu(txh->MacTxControlLow);
if (txs->phyerr)
- brcms_err(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
- txs->phyerr, txh->MainRates);
+ brcms_dbg_tx(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
+ txs->phyerr, txh->MainRates);
if (txs->frameid != le16_to_cpu(txh->TxFrameID)) {
brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n");
--
1.7.11.7
^ permalink raw reply related
* Re: [PATCH 0/6] initval patches
From: Luis R. Rodriguez @ 2013-07-15 19:06 UTC (permalink / raw)
To: Sujith Manoharan; +Cc: linux-wireless
In-Reply-To: <1373601613-31616-1-git-send-email-sujith@msujith.org>
On Thu, Jul 11, 2013 at 9:00 PM, Sujith Manoharan <sujith@msujith.org> wrote:
> From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
>
> This is a resend of the pending initval patches, rebased over
> master.
>
> Sujith Manoharan (6):
> initvals: Update inivals for AR9462 2.0
> initvals: Add 5g-XLNA table for AR9462
> initvals: Add ar9462_2p0_5g_xlna_only_rxgain table
> initvals: Add rxgain tables for AR9462
> initvals: Add support for AR9462 2.1
> initvals: Add mix ob/db tx gain table for AR9462 2.0
Thanks, applied and pushed!
Luis
^ permalink raw reply
* [BUG] 3.10 regression: hang on suspend
From: Ortwin Glück @ 2013-07-15 19:40 UTC (permalink / raw)
To: linux-kernel, sgruszka, linux-wireless
Hi,
My Samsung ultrabook hangs when suspending to RAM since this commit (bisected).
Disabling wifi before suspend works around the issue. All works fine with 3.9.y.
12e7f517029dad819c45eca9ca01fdb9ba57616b
Author: Stanislaw Gruszka <sgruszka@redhat.com>
Date: Thu Feb 28 10:55:26 2013 +0100
mac80211: cleanup generic suspend/resume procedures
Since now we disconnect before suspend, various code which save
connection state can now be removed from suspend and resume
procedure. Cleanup on resume side is smaller as ieee80211_reconfig()
is also used for H/W restart.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Hardware:
01:00.0 Network controller: Intel Corporation Centrino Advanced-N 6235 (rev 24)
Sorry for not noticing this earlier.
Ortwin
^ permalink raw reply
* 802.11p and ath5k v3.10-rc1
From: Emine Nr @ 2013-07-15 21:47 UTC (permalink / raw)
To: linux-wireless
Hello, I'am working on the driver ath5k and the ieee 802.11p. I'am a beginner
on this domain an I need to enable 802.11p on the last version of ath5k driver
(ie backport-3.10-rc1). So I would like to know if somebody know wich are the
main steps to do it.
Thanks for any help.
^ permalink raw reply
* [PATCH 3/6] ath9k: Fix FastChannelChange for AR9462/AR9565
From: Sujith Manoharan @ 2013-07-16 6:33 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1373956402-22169-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Right now, even though these chips support cross-band
FCC, the code is non-functional since we bail out early if
the channelFlags differ. Fix this so that cross-band
FCC works for cards that support this feature.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/hw.c | 45 ++++++++++++++++++++++---------------
1 file changed, 27 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2d385c2..50e5979 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1496,16 +1496,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
+ bool band_switch = false, mode_diff = false;
+ u8 ini_reloaded;
u32 qnum;
int r;
- bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
- bool band_switch, mode_diff;
- u8 ini_reloaded;
- band_switch = (chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ)) !=
- (ah->curchan->channelFlags & (CHANNEL_2GHZ |
- CHANNEL_5GHZ));
- mode_diff = (chan->chanmode != ah->curchan->chanmode);
+ if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) {
+ u32 cur = ah->curchan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ);
+ u32 new = chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ);
+ band_switch = (cur != new);
+ mode_diff = (chan->chanmode != ah->curchan->chanmode);
+ }
for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
if (ath9k_hw_numtxpending(ah, qnum)) {
@@ -1520,7 +1522,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
return false;
}
- if (edma && (band_switch || mode_diff)) {
+ if (band_switch || mode_diff) {
ath9k_hw_mark_phy_inactive(ah);
udelay(5);
@@ -1548,7 +1550,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
ath9k_hw_spur_mitigate_freq(ah, chan);
- if (edma && (band_switch || mode_diff)) {
+ if (band_switch || mode_diff) {
ah->ah_flags |= AH_FASTCC;
if (band_switch || ini_reloaded)
ah->eep_ops->set_board_values(ah, chan);
@@ -1778,16 +1780,11 @@ static void ath9k_hw_init_desc(struct ath_hw *ah)
/*
* Fast channel change:
* (Change synthesizer based on channel freq without resetting chip)
- *
- * Don't do FCC when
- * - Flag is not set
- * - Chip is just coming out of full sleep
- * - Channel to be set is same as current channel
- * - Channel flags are different, (eg.,moving from 2GHz to 5GHz channel)
*/
static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
int ret;
if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
@@ -1806,9 +1803,21 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
(CHANNEL_HALF | CHANNEL_QUARTER))
goto fail;
- if ((chan->channelFlags & CHANNEL_ALL) !=
- (ah->curchan->channelFlags & CHANNEL_ALL))
- goto fail;
+ /*
+ * If cross-band fcc is not supoprted, bail out if
+ * either channelFlags or chanmode differ.
+ *
+ * chanmode will be different if the HT operating mode
+ * changes because of CSA.
+ */
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH)) {
+ if ((chan->channelFlags & CHANNEL_ALL) !=
+ (ah->curchan->channelFlags & CHANNEL_ALL))
+ goto fail;
+
+ if (chan->chanmode != ah->curchan->chanmode)
+ goto fail;
+ }
if (!ath9k_hw_check_alive(ah))
goto fail;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/6] ath9k: Add a HW flag for FCC
From: Sujith Manoharan @ 2013-07-16 6:33 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1373956402-22169-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Fast Channel Change across 2G/5G bands is supported
only by AR9462 and AR9565. Add a HW capability field
to indicate this.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/hw.c | 7 +++++++
drivers/net/wireless/ath/ath9k/hw.h | 1 +
2 files changed, 8 insertions(+)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 4ca0cb0..2d385c2 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2610,6 +2610,13 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
+ /*
+ * Fast channel change across bands is available
+ * only for AR9462 and AR9565.
+ */
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+ pCap->hw_caps |= ATH9K_HW_CAP_FCC_BAND_SWITCH;
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index cd74b3a..fd009e5 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -247,6 +247,7 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_DFS = BIT(16),
ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17),
ATH9K_HW_CAP_PAPRD = BIT(18),
+ ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(19),
};
/*
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/6] ath9k: Move INI overrides to ar9003_hw_override_ini
From: Sujith Manoharan @ 2013-07-16 6:33 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/ar9003_phy.c | 33 ++++++++++++++---------------
1 file changed, 16 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 1f694ab..57e345a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -632,6 +632,22 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+ REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
+ AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
+
+ if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
+ ah->enabled_cals |= TX_IQ_CAL;
+ else
+ ah->enabled_cals &= ~TX_IQ_CAL;
+
+ if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
+ ah->enabled_cals |= TX_CL_CAL;
+ else
+ ah->enabled_cals &= ~TX_CL_CAL;
+ }
}
static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -814,29 +830,12 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
if (chan->channel == 2484)
ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
- if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
- REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
- AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
-
ah->modes_index = modesIndex;
ar9003_hw_override_ini(ah);
ar9003_hw_set_channel_regs(ah, chan);
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
ath9k_hw_apply_txpower(ah, chan, false);
- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
- if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
- AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
- ah->enabled_cals |= TX_IQ_CAL;
- else
- ah->enabled_cals &= ~TX_IQ_CAL;
-
- if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
- ah->enabled_cals |= TX_CL_CAL;
- else
- ah->enabled_cals &= ~TX_CL_CAL;
- }
-
return 0;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 4/6] ath9k: Use correct channel when switching bands
From: Sujith Manoharan @ 2013-07-16 6:33 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1373956402-22169-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/hw.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 50e5979..1dac46d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1526,7 +1526,8 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
ath9k_hw_mark_phy_inactive(ah);
udelay(5);
- ath9k_hw_init_pll(ah, NULL);
+ if (band_switch)
+ ath9k_hw_init_pll(ah, chan);
if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) {
ath_err(common, "Failed to do fast channel change\n");
--
1.8.3.2
^ permalink raw reply related
* [PATCH 5/6] ath9k: Program correct initvals for FCC
From: Sujith Manoharan @ 2013-07-16 6:33 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1373956402-22169-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
* CUS217 specific initvals have to be programmed.
* iniAdditional is not used for AR9462/AR9565, remove it.
* Handle channel 2484 for regulatory compliance.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/ar9003_phy.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 57e345a..2db4ddf 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1517,6 +1517,18 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+ if (AR_SREV_9462_20_OR_LATER(ah)) {
+ /*
+ * CUS217 mix LNA mode.
+ */
+ if (ar9003_hw_get_rx_gain_idx(ah) == 2) {
+ REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_core,
+ 1, regWrites);
+ REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_postamble,
+ modesIndex, regWrites);
+ }
+ }
+
/*
* For 5GHz channels requiring Fast Clock, apply
* different modal values.
@@ -1527,7 +1539,11 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
if (AR_SREV_9565(ah))
REG_WRITE_ARRAY(&ah->iniModesFastClock, 1, regWrites);
- REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
+ /*
+ * JAPAN regulatory.
+ */
+ if (chan->channel == 2484)
+ ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
ah->modes_index = modesIndex;
*ini_reloaded = true;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 6/6] ath9k: Release the RF bus after setting board values
From: Sujith Manoharan @ 2013-07-16 6:33 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1373956402-22169-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/hw.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 1dac46d..ebc9f53 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1498,7 +1498,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_capabilities *pCap = &ah->caps;
bool band_switch = false, mode_diff = false;
- u8 ini_reloaded;
+ u8 ini_reloaded = 0;
u32 qnum;
int r;
@@ -1544,22 +1544,21 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
}
ath9k_hw_set_clockrate(ah);
ath9k_hw_apply_txpower(ah, chan, false);
- ath9k_hw_rfbus_done(ah);
if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
ath9k_hw_set_delta_slope(ah, chan);
ath9k_hw_spur_mitigate_freq(ah, chan);
- if (band_switch || mode_diff) {
- ah->ah_flags |= AH_FASTCC;
- if (band_switch || ini_reloaded)
- ah->eep_ops->set_board_values(ah, chan);
+ if (band_switch || ini_reloaded)
+ ah->eep_ops->set_board_values(ah, chan);
- ath9k_hw_init_bb(ah, chan);
+ ath9k_hw_init_bb(ah, chan);
+ ath9k_hw_rfbus_done(ah);
- if (band_switch || ini_reloaded)
- ath9k_hw_init_cal(ah, chan);
+ if (band_switch || ini_reloaded) {
+ ah->ah_flags |= AH_FASTCC;
+ ath9k_hw_init_cal(ah, chan);
ah->ah_flags &= ~AH_FASTCC;
}
--
1.8.3.2
^ permalink raw reply related
* Re: [BUG] 3.10 regression: hang on suspend
From: Stanislaw Gruszka @ 2013-07-16 6:56 UTC (permalink / raw)
To: Ortwin Glück; +Cc: linux-kernel, linux-wireless
In-Reply-To: <51E4501D.3010001@odi.ch>
Hi
On Mon, Jul 15, 2013 at 09:40:13PM +0200, Ortwin Glück wrote:
> My Samsung ultrabook hangs when suspending to RAM since this commit
> (bisected). Disabling wifi before suspend works around the issue.
> All works fine with 3.9.y.
>
> 12e7f517029dad819c45eca9ca01fdb9ba57616b
>
> Author: Stanislaw Gruszka <sgruszka@redhat.com>
>
> Date: Thu Feb 28 10:55:26 2013 +0100
>
> mac80211: cleanup generic suspend/resume procedures
>
> Since now we disconnect before suspend, various code which save
> connection state can now be removed from suspend and resume
> procedure. Cleanup on resume side is smaller as ieee80211_reconfig()
> is also used for H/W restart.
>
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Apparently this commit changed suspend procedure on mac80211, but it's
not obvious for me why it hangs :-(
What is your user space configuration (are you using NM or other
software or maybe just wpa_supplicant)? Are you using wowlan?
If you do add no_console_suspend boot parameter does it print some
diagnostic messages during suspend before the hang ?
Thanks
Stanislaw
^ permalink raw reply
* [PATCH v3 00/10] ath10k: device setup refactor
From: Michal Kazior @ 2013-07-16 7:19 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1371041642-20273-1-git-send-email-michal.kazior@tieto.com>
This is a respin of my patchset that addresses
hibernation issues.
This is also groundwork for proper hw recovery
that I'm going to post too.
v3:
* update comments in pci logic decoupling
* add missing commit message for one of the patches
* update commit message for free_vdev_map patch
Michal Kazior (10):
ath10k: decouple pci start/stop logic
ath10k: decouple core start/stop logic
ath10k: allow deferred regd update
ath10k: reset BMI state upon init
ath10k: decouple suspend code
ath10k: move free_vdev_map initialization
ath10k: make sure all resources are freed upon ath10k_stop()
ath10k: defer hw setup to start/stop mac80211 hooks
ath10k: store firmware files in memory
ath10k: skip fw stats debugfs interface if device is down
drivers/net/wireless/ath/ath10k/bmi.c | 6 +
drivers/net/wireless/ath/ath10k/bmi.h | 1 +
drivers/net/wireless/ath/ath10k/core.c | 249 +++++++++++++++++----------
drivers/net/wireless/ath/ath10k/core.h | 16 +-
drivers/net/wireless/ath/ath10k/debug.c | 30 ++--
drivers/net/wireless/ath/ath10k/hif.h | 39 +++++
drivers/net/wireless/ath/ath10k/mac.c | 151 ++++++++++++++++-
drivers/net/wireless/ath/ath10k/pci.c | 283 +++++++++++++------------------
8 files changed, 497 insertions(+), 278 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH v3 01/10] ath10k: decouple pci start/stop logic
From: Michal Kazior @ 2013-07-16 7:19 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1373959193-5164-1-git-send-email-michal.kazior@tieto.com>
Split logic that prepares the device for BMI
phase/cleans up related resources.
This is necessary for ath10k to be able to restart
hw on the fly without reloading the module.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/hif.h | 20 ++++++
drivers/net/wireless/ath/ath10k/pci.c | 110 +++++++++++++++++++++------------
2 files changed, 91 insertions(+), 39 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 010e265..00d2940 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -46,8 +46,11 @@ struct ath10k_hif_ops {
void *request, u32 request_len,
void *response, u32 *response_len);
+ /* Post BMI phase, after FW is loaded. Starts regular operation */
int (*start)(struct ath10k *ar);
+ /* Clean up what start() did. This does not revert to BMI phase. If
+ * desired so, call power_down() and power_up() */
void (*stop)(struct ath10k *ar);
int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id,
@@ -70,6 +73,13 @@ struct ath10k_hif_ops {
struct ath10k_hif_cb *callbacks);
u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
+
+ /* Power up the device and enter BMI transfer mode for FW download */
+ int (*power_up)(struct ath10k *ar);
+
+ /* Power down the device and free up resources. stop() must be called
+ * before this if start() was called earlier */
+ void (*power_down)(struct ath10k *ar);
};
@@ -134,4 +144,14 @@ static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
return ar->hif.ops->get_free_queue_number(ar, pipe_id);
}
+static inline int ath10k_hif_power_up(struct ath10k *ar)
+{
+ return ar->hif.ops->power_up(ar);
+}
+
+static inline void ath10k_hif_power_down(struct ath10k *ar)
+{
+ ar->hif.ops->power_down(ar);
+}
+
#endif /* _HIF_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 7da0983..c15b0c5 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -54,6 +54,8 @@ static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info,
int num);
static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info);
static void ath10k_pci_stop_ce(struct ath10k *ar);
+static void ath10k_pci_device_reset(struct ath10k *ar);
+static int ath10k_pci_reset_target(struct ath10k *ar);
static const struct ce_attr host_ce_config_wlan[] = {
/* host->target HTC control and raw streams */
@@ -1734,6 +1736,66 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
ath10k_pci_sleep(ar);
}
+static int ath10k_pci_hif_power_up(struct ath10k *ar)
+{
+ int ret;
+
+ /*
+ * Bring the target up cleanly.
+ *
+ * The target may be in an undefined state with an AUX-powered Target
+ * and a Host in WoW mode. If the Host crashes, loses power, or is
+ * restarted (without unloading the driver) then the Target is left
+ * (aux) powered and running. On a subsequent driver load, the Target
+ * is in an unexpected state. We try to catch that here in order to
+ * reset the Target and retry the probe.
+ */
+ ath10k_pci_device_reset(ar);
+
+ ret = ath10k_pci_reset_target(ar);
+ if (ret)
+ goto err;
+
+ if (ath10k_target_ps) {
+ ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n");
+ } else {
+ /* Force AWAKE forever */
+ ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save disabled\n");
+ ath10k_do_pci_wake(ar);
+ }
+
+ ret = ath10k_pci_ce_init(ar);
+ if (ret)
+ goto err_ps;
+
+ ret = ath10k_pci_init_config(ar);
+ if (ret)
+ goto err_ce;
+
+ ret = ath10k_pci_wake_target_cpu(ar);
+ if (ret) {
+ ath10k_err("could not wake up target CPU (%d)\n", ret);
+ goto err_ce;
+ }
+
+ return 0;
+
+err_ce:
+ ath10k_pci_ce_deinit(ar);
+err_ps:
+ if (!ath10k_target_ps)
+ ath10k_do_pci_sleep(ar);
+err:
+ return ret;
+}
+
+static void ath10k_pci_hif_power_down(struct ath10k *ar)
+{
+ ath10k_pci_ce_deinit(ar);
+ if (!ath10k_target_ps)
+ ath10k_do_pci_sleep(ar);
+}
+
static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
.send_head = ath10k_pci_hif_send_head,
.exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg,
@@ -1744,6 +1806,8 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
.send_complete_check = ath10k_pci_hif_send_complete_check,
.set_callbacks = ath10k_pci_hif_set_callbacks,
.get_free_queue_number = ath10k_pci_hif_get_free_queue_number,
+ .power_up = ath10k_pci_hif_power_up,
+ .power_down = ath10k_pci_hif_power_down,
};
static void ath10k_pci_ce_tasklet(unsigned long ptr)
@@ -2245,54 +2309,22 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_iomap;
}
- /*
- * Bring the target up cleanly.
- *
- * The target may be in an undefined state with an AUX-powered Target
- * and a Host in WoW mode. If the Host crashes, loses power, or is
- * restarted (without unloading the driver) then the Target is left
- * (aux) powered and running. On a subsequent driver load, the Target
- * is in an unexpected state. We try to catch that here in order to
- * reset the Target and retry the probe.
- */
- ath10k_pci_device_reset(ar);
-
- ret = ath10k_pci_reset_target(ar);
- if (ret)
- goto err_intr;
-
- if (ath10k_target_ps) {
- ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n");
- } else {
- /* Force AWAKE forever */
- ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save disabled\n");
- ath10k_do_pci_wake(ar);
- }
-
- ret = ath10k_pci_ce_init(ar);
- if (ret)
- goto err_intr;
-
- ret = ath10k_pci_init_config(ar);
- if (ret)
- goto err_ce;
-
- ret = ath10k_pci_wake_target_cpu(ar);
+ ret = ath10k_pci_hif_power_up(ar);
if (ret) {
- ath10k_err("could not wake up target CPU (%d)\n", ret);
- goto err_ce;
+ ath10k_err("could not start pci hif (%d)\n", ret);
+ goto err_intr;
}
ret = ath10k_core_register(ar);
if (ret) {
ath10k_err("could not register driver core (%d)\n", ret);
- goto err_ce;
+ goto err_hif;
}
return 0;
-err_ce:
- ath10k_pci_ce_deinit(ar);
+err_hif:
+ ath10k_pci_hif_power_down(ar);
err_intr:
ath10k_pci_stop_intr(ar);
err_iomap:
@@ -2331,7 +2363,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
tasklet_kill(&ar_pci->msi_fw_err);
ath10k_core_unregister(ar);
- ath10k_pci_ce_deinit(ar);
+ ath10k_pci_hif_power_down(ar);
ath10k_pci_stop_intr(ar);
pci_set_drvdata(pdev, NULL);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 03/10] ath10k: allow deferred regd update
From: Michal Kazior @ 2013-07-16 7:19 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1373959193-5164-1-git-send-email-michal.kazior@tieto.com>
Regulatory domain notification hook can be called
regardless of the hw state (i.e. before start
mac80211 callback).
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/core.h | 7 +++++++
drivers/net/wireless/ath/ath10k/mac.c | 26 +++++++++++++++++++-------
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 5a0b2ce..d5b2533 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -247,6 +247,11 @@ struct ath10k_debug {
struct completion event_stats_compl;
};
+enum ath10k_state {
+ ATH10K_STATE_OFF = 0,
+ ATH10K_STATE_ON,
+};
+
struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
@@ -344,6 +349,8 @@ struct ath10k {
struct completion offchan_tx_completed;
struct sk_buff *offchan_tx_skb;
+ enum ath10k_state state;
+
#ifdef CONFIG_ATH10K_DEBUGFS
struct ath10k_debug debug;
#endif
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 5082503..4627c16 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1310,23 +1310,19 @@ static int ath10k_update_channel_list(struct ath10k *ar)
return ret;
}
-static void ath10k_reg_notifier(struct wiphy *wiphy,
- struct regulatory_request *request)
+static void ath10k_regd_update(struct ath10k *ar)
{
- struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct reg_dmn_pair_mapping *regpair;
- struct ath10k *ar = hw->priv;
int ret;
- mutex_lock(&ar->conf_mutex);
-
- ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
+ lockdep_assert_held(&ar->conf_mutex);
ret = ath10k_update_channel_list(ar);
if (ret)
ath10k_warn("could not update channel list (%d)\n", ret);
regpair = ar->ath_common.regulatory.regpair;
+
/* Target allows setting up per-band regdomain but ath_common provides
* a combined one only */
ret = ath10k_wmi_pdev_set_regdomain(ar,
@@ -1337,7 +1333,19 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
regpair->reg_5ghz_ctl);
if (ret)
ath10k_warn("could not set pdev regdomain (%d)\n", ret);
+}
+static void ath10k_reg_notifier(struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct ath10k *ar = hw->priv;
+
+ ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
+
+ mutex_lock(&ar->conf_mutex);
+ if (ar->state == ATH10K_STATE_ON)
+ ath10k_regd_update(ar);
mutex_unlock(&ar->conf_mutex);
}
@@ -1732,6 +1740,9 @@ static int ath10k_start(struct ieee80211_hw *hw)
ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
ret);
+ ar->state = ATH10K_STATE_ON;
+ ath10k_regd_update(ar);
+
mutex_unlock(&ar->conf_mutex);
return 0;
}
@@ -1742,6 +1753,7 @@ static void ath10k_stop(struct ieee80211_hw *hw)
mutex_lock(&ar->conf_mutex);
ath10k_offchan_tx_purge(ar);
+ ar->state = ATH10K_STATE_OFF;
mutex_unlock(&ar->conf_mutex);
cancel_work_sync(&ar->offchan_tx_work);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 02/10] ath10k: decouple core start/stop logic
From: Michal Kazior @ 2013-07-16 7:19 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1373959193-5164-1-git-send-email-michal.kazior@tieto.com>
Enables code reuse for proper hw reconfiguration
that is in turn required for proper
suspend/hibernation/wowlan support.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/core.c | 44 +++++++++++++++++++++++---------
drivers/net/wireless/ath/ath10k/core.h | 2 ++
2 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index f1312fa..dcddae4 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -502,8 +502,7 @@ void ath10k_core_destroy(struct ath10k *ar)
}
EXPORT_SYMBOL(ath10k_core_destroy);
-
-int ath10k_core_register(struct ath10k *ar)
+int ath10k_core_start(struct ath10k *ar)
{
struct bmi_target_info target_info;
int status;
@@ -589,9 +588,36 @@ int ath10k_core_register(struct ath10k *ar)
if (status)
goto err_disconnect_htc;
+ return 0;
+
+err_disconnect_htc:
+ ath10k_htc_stop(&ar->htc);
+err_htt_detach:
+ ath10k_htt_detach(&ar->htt);
+err_wmi_detach:
+ ath10k_wmi_detach(ar);
+err:
+ return status;
+}
+
+void ath10k_core_stop(struct ath10k *ar)
+{
+ ath10k_htc_stop(&ar->htc);
+ ath10k_htt_detach(&ar->htt);
+ ath10k_wmi_detach(ar);
+}
+
+int ath10k_core_register(struct ath10k *ar)
+{
+ int status;
+
+ status = ath10k_core_start(ar);
+ if (status)
+ goto err;
+
status = ath10k_mac_register(ar);
if (status)
- goto err_disconnect_htc;
+ goto err_core_stop;
status = ath10k_debug_create(ar);
if (status) {
@@ -603,12 +629,8 @@ int ath10k_core_register(struct ath10k *ar)
err_unregister_mac:
ath10k_mac_unregister(ar);
-err_disconnect_htc:
- ath10k_htc_stop(&ar->htc);
-err_htt_detach:
- ath10k_htt_detach(&ar->htt);
-err_wmi_detach:
- ath10k_wmi_detach(ar);
+err_core_stop:
+ ath10k_core_stop(ar);
err:
return status;
}
@@ -620,9 +642,7 @@ void ath10k_core_unregister(struct ath10k *ar)
* Otherwise we will fail to submit commands to FW and mac80211 will be
* unhappy about callback failures. */
ath10k_mac_unregister(ar);
- ath10k_htc_stop(&ar->htc);
- ath10k_htt_detach(&ar->htt);
- ath10k_wmi_detach(ar);
+ ath10k_core_stop(ar);
}
EXPORT_SYMBOL(ath10k_core_unregister);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 2f7065c..5a0b2ce 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -353,6 +353,8 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
const struct ath10k_hif_ops *hif_ops);
void ath10k_core_destroy(struct ath10k *ar);
+int ath10k_core_start(struct ath10k *ar);
+void ath10k_core_stop(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar);
void ath10k_core_unregister(struct ath10k *ar);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 04/10] ath10k: reset BMI state upon init
From: Michal Kazior @ 2013-07-16 7:19 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1373959193-5164-1-git-send-email-michal.kazior@tieto.com>
This is necessary if we want to be able to restart
hw on-the-fly.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/bmi.c | 6 ++++++
drivers/net/wireless/ath/ath10k/bmi.h | 1 +
drivers/net/wireless/ath/ath10k/core.c | 2 ++
3 files changed, 9 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c
index aeae029..744da6d 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.c
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
@@ -20,6 +20,12 @@
#include "debug.h"
#include "htc.h"
+void ath10k_bmi_start(struct ath10k *ar)
+{
+ ath10k_dbg(ATH10K_DBG_CORE, "BMI started\n");
+ ar->bmi.done_sent = false;
+}
+
int ath10k_bmi_done(struct ath10k *ar)
{
struct bmi_cmd cmd;
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 32c56aa..8d81ce1 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -184,6 +184,7 @@ struct bmi_target_info {
#define BMI_CE_NUM_TO_TARG 0
#define BMI_CE_NUM_TO_HOST 1
+void ath10k_bmi_start(struct ath10k *ar);
int ath10k_bmi_done(struct ath10k *ar);
int ath10k_bmi_get_target_info(struct ath10k *ar,
struct bmi_target_info *target_info);
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index dcddae4..3d75c6a 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -507,6 +507,8 @@ int ath10k_core_start(struct ath10k *ar)
struct bmi_target_info target_info;
int status;
+ ath10k_bmi_start(ar);
+
memset(&target_info, 0, sizeof(target_info));
status = ath10k_bmi_get_target_info(ar, &target_info);
if (status)
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 06/10] ath10k: move free_vdev_map initialization
From: Michal Kazior @ 2013-07-16 7:19 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1373959193-5164-1-git-send-email-michal.kazior@tieto.com>
This is necessary for hw reconfiguration to work.
Since mac80211 is not calling remove_interface()
is such case we must reset free_vdev_map.
Also use a define instead of a hardcoded value for
vdev map initialization.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 01c1d82..0e4a704 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -458,8 +458,6 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
ar->hif.priv = hif_priv;
ar->hif.ops = hif_ops;
- ar->free_vdev_map = 0xFF; /* 8 vdevs */
-
init_completion(&ar->scan.started);
init_completion(&ar->scan.completed);
init_completion(&ar->scan.on_channel);
@@ -590,6 +588,8 @@ int ath10k_core_start(struct ath10k *ar)
if (status)
goto err_disconnect_htc;
+ ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
+
return 0;
err_disconnect_htc:
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 05/10] ath10k: decouple suspend code
From: Michal Kazior @ 2013-07-16 7:19 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1373959193-5164-1-git-send-email-michal.kazior@tieto.com>
Split up fw-related and hw-related suspension code.
Although we don't advertise WoW support to
mac80211 yet it's useful to keep the code in
suspend/resume hooks.
At this point there's no need to keep pci pm ops.
In case of WoW mac80211 calls ath10k_suspend()
which should take care of entering low-power mode.
In case WoW is not available mac80211 will go
through regular interface teradown and use start/stop.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/core.c | 28 -----
drivers/net/wireless/ath/ath10k/core.h | 3 -
drivers/net/wireless/ath/ath10k/hif.h | 19 ++++
drivers/net/wireless/ath/ath10k/mac.c | 66 ++++++++++++
drivers/net/wireless/ath/ath10k/pci.c | 176 ++++++++++----------------------
5 files changed, 138 insertions(+), 154 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 3d75c6a..01c1d82 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -648,34 +648,6 @@ void ath10k_core_unregister(struct ath10k *ar)
}
EXPORT_SYMBOL(ath10k_core_unregister);
-int ath10k_core_target_suspend(struct ath10k *ar)
-{
- int ret;
-
- ath10k_dbg(ATH10K_DBG_CORE, "%s: called", __func__);
-
- ret = ath10k_wmi_pdev_suspend_target(ar);
- if (ret)
- ath10k_warn("could not suspend target (%d)\n", ret);
-
- return ret;
-}
-EXPORT_SYMBOL(ath10k_core_target_suspend);
-
-int ath10k_core_target_resume(struct ath10k *ar)
-{
- int ret;
-
- ath10k_dbg(ATH10K_DBG_CORE, "%s: called", __func__);
-
- ret = ath10k_wmi_pdev_resume_target(ar);
- if (ret)
- ath10k_warn("could not resume target (%d)\n", ret);
-
- return ret;
-}
-EXPORT_SYMBOL(ath10k_core_target_resume);
-
MODULE_AUTHOR("Qualcomm Atheros");
MODULE_DESCRIPTION("Core module for QCA988X PCIe devices.");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index d5b2533..5c94ea0 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -365,7 +365,4 @@ void ath10k_core_stop(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar);
void ath10k_core_unregister(struct ath10k *ar);
-int ath10k_core_target_suspend(struct ath10k *ar);
-int ath10k_core_target_resume(struct ath10k *ar);
-
#endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 00d2940..dcdea68 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -80,6 +80,9 @@ struct ath10k_hif_ops {
/* Power down the device and free up resources. stop() must be called
* before this if start() was called earlier */
void (*power_down)(struct ath10k *ar);
+
+ int (*suspend)(struct ath10k *ar);
+ int (*resume)(struct ath10k *ar);
};
@@ -154,4 +157,20 @@ static inline void ath10k_hif_power_down(struct ath10k *ar)
ar->hif.ops->power_down(ar);
}
+static inline int ath10k_hif_suspend(struct ath10k *ar)
+{
+ if (!ar->hif.ops->suspend)
+ return -EOPNOTSUPP;
+
+ return ar->hif.ops->suspend(ar);
+}
+
+static inline int ath10k_hif_resume(struct ath10k *ar)
+{
+ if (!ar->hif.ops->resume)
+ return -EOPNOTSUPP;
+
+ return ar->hif.ops->resume(ar);
+}
+
#endif /* _HIF_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 4627c16..febba7d 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -20,6 +20,7 @@
#include <net/mac80211.h>
#include <linux/etherdevice.h>
+#include "hif.h"
#include "core.h"
#include "debug.h"
#include "wmi.h"
@@ -2749,6 +2750,67 @@ static int ath10k_tx_last_beacon(struct ieee80211_hw *hw)
return 1;
}
+#ifdef CONFIG_PM
+static int ath10k_suspend(struct ieee80211_hw *hw,
+ struct cfg80211_wowlan *wowlan)
+{
+ struct ath10k *ar = hw->priv;
+ int ret;
+
+ ar->is_target_paused = false;
+
+ ret = ath10k_wmi_pdev_suspend_target(ar);
+ if (ret) {
+ ath10k_warn("could not suspend target (%d)\n", ret);
+ return 1;
+ }
+
+ ret = wait_event_interruptible_timeout(ar->event_queue,
+ ar->is_target_paused == true,
+ 1 * HZ);
+ if (ret < 0) {
+ ath10k_warn("suspend interrupted (%d)\n", ret);
+ goto resume;
+ } else if (ret == 0) {
+ ath10k_warn("suspend timed out - target pause event never came\n");
+ goto resume;
+ }
+
+ ret = ath10k_hif_suspend(ar);
+ if (ret) {
+ ath10k_warn("could not suspend hif (%d)\n", ret);
+ goto resume;
+ }
+
+ return 0;
+resume:
+ ret = ath10k_wmi_pdev_resume_target(ar);
+ if (ret)
+ ath10k_warn("could not resume target (%d)\n", ret);
+ return 1;
+}
+
+static int ath10k_resume(struct ieee80211_hw *hw)
+{
+ struct ath10k *ar = hw->priv;
+ int ret;
+
+ ret = ath10k_hif_resume(ar);
+ if (ret) {
+ ath10k_warn("could not resume hif (%d)\n", ret);
+ return 1;
+ }
+
+ ret = ath10k_wmi_pdev_resume_target(ar);
+ if (ret) {
+ ath10k_warn("could not resume target (%d)\n", ret);
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
static const struct ieee80211_ops ath10k_ops = {
.tx = ath10k_tx,
.start = ath10k_start,
@@ -2769,6 +2831,10 @@ static const struct ieee80211_ops ath10k_ops = {
.set_frag_threshold = ath10k_set_frag_threshold,
.flush = ath10k_flush,
.tx_last_beacon = ath10k_tx_last_beacon,
+#ifdef CONFIG_PM
+ .suspend = ath10k_suspend,
+ .resume = ath10k_resume,
+#endif
};
#define RATETAB_ENT(_rate, _rateid, _flags) { \
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index c15b0c5..75f5427 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1796,6 +1796,55 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar)
ath10k_do_pci_sleep(ar);
}
+#ifdef CONFIG_PM
+
+#define ATH10K_PCI_PM_CONTROL 0x44
+
+static int ath10k_pci_hif_suspend(struct ath10k *ar)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ struct pci_dev *pdev = ar_pci->pdev;
+ u32 val;
+
+ pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
+
+ if ((val & 0x000000ff) != 0x3) {
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
+ (val & 0xffffff00) | 0x03);
+ }
+
+ return 0;
+}
+
+static int ath10k_pci_hif_resume(struct ath10k *ar)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ struct pci_dev *pdev = ar_pci->pdev;
+ u32 val;
+
+ pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
+
+ if ((val & 0x000000ff) != 0) {
+ pci_restore_state(pdev);
+ pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
+ val & 0xffffff00);
+ /*
+ * Suspend/Resume resets the PCI configuration space,
+ * so we have to re-disable the RETRY_TIMEOUT register (0x41)
+ * to keep PCI Tx retries from interfering with C3 CPU state
+ */
+ pci_read_config_dword(pdev, 0x40, &val);
+
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+ }
+
+ return 0;
+}
+#endif
+
static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
.send_head = ath10k_pci_hif_send_head,
.exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg,
@@ -1808,6 +1857,10 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
.get_free_queue_number = ath10k_pci_hif_get_free_queue_number,
.power_up = ath10k_pci_hif_power_up,
.power_down = ath10k_pci_hif_power_down,
+#ifdef CONFIG_PM
+ .suspend = ath10k_pci_hif_suspend,
+ .resume = ath10k_pci_hif_resume,
+#endif
};
static void ath10k_pci_ce_tasklet(unsigned long ptr)
@@ -2376,128 +2429,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
kfree(ar_pci);
}
-#if defined(CONFIG_PM_SLEEP)
-
-#define ATH10K_PCI_PM_CONTROL 0x44
-
-static int ath10k_pci_suspend(struct device *device)
-{
- struct pci_dev *pdev = to_pci_dev(device);
- struct ath10k *ar = pci_get_drvdata(pdev);
- struct ath10k_pci *ar_pci;
- u32 val;
- int ret, retval;
-
- ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__);
-
- if (!ar)
- return -ENODEV;
-
- ar_pci = ath10k_pci_priv(ar);
- if (!ar_pci)
- return -ENODEV;
-
- if (ath10k_core_target_suspend(ar))
- return -EBUSY;
-
- ret = wait_event_interruptible_timeout(ar->event_queue,
- ar->is_target_paused == true,
- 1 * HZ);
- if (ret < 0) {
- ath10k_warn("suspend interrupted (%d)\n", ret);
- retval = ret;
- goto resume;
- } else if (ret == 0) {
- ath10k_warn("suspend timed out - target pause event never came\n");
- retval = EIO;
- goto resume;
- }
-
- /*
- * reset is_target_paused and host can check that in next time,
- * or it will always be TRUE and host just skip the waiting
- * condition, it causes target assert due to host already
- * suspend
- */
- ar->is_target_paused = false;
-
- pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
-
- if ((val & 0x000000ff) != 0x3) {
- pci_save_state(pdev);
- pci_disable_device(pdev);
- pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
- (val & 0xffffff00) | 0x03);
- }
-
- return 0;
-resume:
- ret = ath10k_core_target_resume(ar);
- if (ret)
- ath10k_warn("could not resume (%d)\n", ret);
-
- return retval;
-}
-
-static int ath10k_pci_resume(struct device *device)
-{
- struct pci_dev *pdev = to_pci_dev(device);
- struct ath10k *ar = pci_get_drvdata(pdev);
- struct ath10k_pci *ar_pci;
- int ret;
- u32 val;
-
- ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__);
-
- if (!ar)
- return -ENODEV;
- ar_pci = ath10k_pci_priv(ar);
-
- if (!ar_pci)
- return -ENODEV;
-
- ret = pci_enable_device(pdev);
- if (ret) {
- ath10k_warn("cannot enable PCI device: %d\n", ret);
- return ret;
- }
-
- pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
-
- if ((val & 0x000000ff) != 0) {
- pci_restore_state(pdev);
- pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
- val & 0xffffff00);
- /*
- * Suspend/Resume resets the PCI configuration space,
- * so we have to re-disable the RETRY_TIMEOUT register (0x41)
- * to keep PCI Tx retries from interfering with C3 CPU state
- */
- pci_read_config_dword(pdev, 0x40, &val);
-
- if ((val & 0x0000ff00) != 0)
- pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
- }
-
- ret = ath10k_core_target_resume(ar);
- if (ret)
- ath10k_warn("target resume failed: %d\n", ret);
-
- return ret;
-}
-
-static SIMPLE_DEV_PM_OPS(ath10k_dev_pm_ops,
- ath10k_pci_suspend,
- ath10k_pci_resume);
-
-#define ATH10K_PCI_PM_OPS (&ath10k_dev_pm_ops)
-
-#else
-
-#define ATH10K_PCI_PM_OPS NULL
-
-#endif /* CONFIG_PM_SLEEP */
-
MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table);
static struct pci_driver ath10k_pci_driver = {
@@ -2505,7 +2436,6 @@ static struct pci_driver ath10k_pci_driver = {
.id_table = ath10k_pci_id_table,
.probe = ath10k_pci_probe,
.remove = ath10k_pci_remove,
- .driver.pm = ATH10K_PCI_PM_OPS,
};
static int __init ath10k_pci_init(void)
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 07/10] ath10k: make sure all resources are freed upon ath10k_stop()
From: Michal Kazior @ 2013-07-16 7:19 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1373959193-5164-1-git-send-email-michal.kazior@tieto.com>
This is necessary for proper hw reconfiguration
and to avoid memory leaks.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/mac.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index febba7d..b9663e9 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -369,6 +369,20 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
spin_unlock_bh(&ar->data_lock);
}
+static void ath10k_peer_cleanup_all(struct ath10k *ar)
+{
+ struct ath10k_peer *peer, *tmp;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ spin_lock_bh(&ar->data_lock);
+ list_for_each_entry_safe(peer, tmp, &ar->peers, list) {
+ list_del(&peer->list);
+ kfree(peer);
+ }
+ spin_unlock_bh(&ar->data_lock);
+}
+
/************************/
/* Interface management */
/************************/
@@ -1753,7 +1767,18 @@ static void ath10k_stop(struct ieee80211_hw *hw)
struct ath10k *ar = hw->priv;
mutex_lock(&ar->conf_mutex);
+ del_timer_sync(&ar->scan.timeout);
ath10k_offchan_tx_purge(ar);
+ ath10k_peer_cleanup_all(ar);
+
+ spin_lock_bh(&ar->data_lock);
+ if (ar->scan.in_progress) {
+ del_timer(&ar->scan.timeout);
+ ar->scan.in_progress = false;
+ ieee80211_scan_completed(ar->hw, true);
+ }
+ spin_unlock_bh(&ar->data_lock);
+
ar->state = ATH10K_STATE_OFF;
mutex_unlock(&ar->conf_mutex);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 08/10] ath10k: defer hw setup to start/stop mac80211 hooks
From: Michal Kazior @ 2013-07-16 7:19 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1373959193-5164-1-git-send-email-michal.kazior@tieto.com>
This fixes suspend-to-disk. The hardware is now
re-initialized upon freeze/thaw properly.
This also makes suspend/resume re-initialize the
hardware as WoWLAN support is not done yet.
With some little work it should be possible to
support hw reconfiguration for hw/fw recovery.
HW must be initialized once before registering to
mac80211 because FW determinates what hw
capabilities can be advertised.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
drivers/net/wireless/ath/ath10k/core.c | 46 +++++++++++++++++++++-----
drivers/net/wireless/ath/ath10k/mac.c | 56 ++++++++++++++++++++++++--------
drivers/net/wireless/ath/ath10k/pci.c | 11 +------
3 files changed, 81 insertions(+), 32 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 0e4a704..1d4c245 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -601,6 +601,7 @@ err_wmi_detach:
err:
return status;
}
+EXPORT_SYMBOL(ath10k_core_start);
void ath10k_core_stop(struct ath10k *ar)
{
@@ -608,18 +609,49 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_htt_detach(&ar->htt);
ath10k_wmi_detach(ar);
}
+EXPORT_SYMBOL(ath10k_core_stop);
+
+/* mac80211 manages fw/hw initialization through start/stop hooks. However in
+ * order to know what hw capabilities should be advertised to mac80211 it is
+ * necessary to load the firmware (and tear it down immediately since start
+ * hook will try to init it again) before registering */
+static int ath10k_core_probe_fw(struct ath10k *ar)
+{
+ int ret;
+
+ ret = ath10k_hif_power_up(ar);
+ if (ret) {
+ ath10k_err("could not start pci hif (%d)\n", ret);
+ return ret;
+ }
+
+ ret = ath10k_core_start(ar);
+ if (ret) {
+ ath10k_err("could not init core (%d)\n", ret);
+ ath10k_hif_power_down(ar);
+ return ret;
+ }
+
+ ath10k_core_stop(ar);
+ ath10k_hif_power_down(ar);
+ return 0;
+}
int ath10k_core_register(struct ath10k *ar)
{
int status;
- status = ath10k_core_start(ar);
- if (status)
- goto err;
+ status = ath10k_core_probe_fw(ar);
+ if (status) {
+ ath10k_err("could not probe fw (%d)\n", status);
+ return status;
+ }
status = ath10k_mac_register(ar);
- if (status)
- goto err_core_stop;
+ if (status) {
+ ath10k_err("could not register to mac80211 (%d)\n", status);
+ return status;
+ }
status = ath10k_debug_create(ar);
if (status) {
@@ -631,9 +663,6 @@ int ath10k_core_register(struct ath10k *ar)
err_unregister_mac:
ath10k_mac_unregister(ar);
-err_core_stop:
- ath10k_core_stop(ar);
-err:
return status;
}
EXPORT_SYMBOL(ath10k_core_register);
@@ -644,7 +673,6 @@ void ath10k_core_unregister(struct ath10k *ar)
* Otherwise we will fail to submit commands to FW and mac80211 will be
* unhappy about callback failures. */
ath10k_mac_unregister(ar);
- ath10k_core_stop(ar);
}
EXPORT_SYMBOL(ath10k_core_unregister);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b9663e9..2dfd446 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1738,13 +1738,52 @@ static void ath10k_tx(struct ieee80211_hw *hw,
/*
* Initialize various parameters with default vaules.
*/
+static void ath10k_halt(struct ath10k *ar)
+{
+ lockdep_assert_held(&ar->conf_mutex);
+
+ del_timer_sync(&ar->scan.timeout);
+ ath10k_offchan_tx_purge(ar);
+ ath10k_peer_cleanup_all(ar);
+ ath10k_core_stop(ar);
+ ath10k_hif_power_down(ar);
+
+ spin_lock_bh(&ar->data_lock);
+ if (ar->scan.in_progress) {
+ del_timer(&ar->scan.timeout);
+ ar->scan.in_progress = false;
+ ieee80211_scan_completed(ar->hw, true);
+ }
+ spin_unlock_bh(&ar->data_lock);
+}
+
static int ath10k_start(struct ieee80211_hw *hw)
{
struct ath10k *ar = hw->priv;
- int ret;
+ int ret = 0;
mutex_lock(&ar->conf_mutex);
+ if (ar->state != ATH10K_STATE_OFF) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ret = ath10k_hif_power_up(ar);
+ if (ret) {
+ ath10k_err("could not init hif (%d)\n", ret);
+ ar->state = ATH10K_STATE_OFF;
+ goto exit;
+ }
+
+ ret = ath10k_core_start(ar);
+ if (ret) {
+ ath10k_err("could not init core (%d)\n", ret);
+ ath10k_hif_power_down(ar);
+ ar->state = ATH10K_STATE_OFF;
+ goto exit;
+ }
+
ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1);
if (ret)
ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n",
@@ -1755,9 +1794,9 @@ static int ath10k_start(struct ieee80211_hw *hw)
ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
ret);
- ar->state = ATH10K_STATE_ON;
ath10k_regd_update(ar);
+exit:
mutex_unlock(&ar->conf_mutex);
return 0;
}
@@ -1767,17 +1806,8 @@ static void ath10k_stop(struct ieee80211_hw *hw)
struct ath10k *ar = hw->priv;
mutex_lock(&ar->conf_mutex);
- del_timer_sync(&ar->scan.timeout);
- ath10k_offchan_tx_purge(ar);
- ath10k_peer_cleanup_all(ar);
-
- spin_lock_bh(&ar->data_lock);
- if (ar->scan.in_progress) {
- del_timer(&ar->scan.timeout);
- ar->scan.in_progress = false;
- ieee80211_scan_completed(ar->hw, true);
- }
- spin_unlock_bh(&ar->data_lock);
+ if (ar->state == ATH10K_STATE_ON)
+ ath10k_halt(ar);
ar->state = ATH10K_STATE_OFF;
mutex_unlock(&ar->conf_mutex);
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 75f5427..bfe8561 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -2362,22 +2362,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_iomap;
}
- ret = ath10k_pci_hif_power_up(ar);
- if (ret) {
- ath10k_err("could not start pci hif (%d)\n", ret);
- goto err_intr;
- }
-
ret = ath10k_core_register(ar);
if (ret) {
ath10k_err("could not register driver core (%d)\n", ret);
- goto err_hif;
+ goto err_intr;
}
return 0;
-err_hif:
- ath10k_pci_hif_power_down(ar);
err_intr:
ath10k_pci_stop_intr(ar);
err_iomap:
@@ -2416,7 +2408,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
tasklet_kill(&ar_pci->msi_fw_err);
ath10k_core_unregister(ar);
- ath10k_pci_hif_power_down(ar);
ath10k_pci_stop_intr(ar);
pci_set_drvdata(pdev, NULL);
--
1.7.9.5
^ 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