* Re: [PATCH] Implementation of the IEEE80211_RADIOTAP_RATE option
From: Rafael Laufer @ 2009-08-21 18:03 UTC (permalink / raw)
To: Gábor Stefanik; +Cc: Johannes Berg, linux-wireless
In-Reply-To: <69e28c910908210630m47eda1eegcd502c212736decd@mail.gmail.com>
Gábor Stefanik wrote:
>
> Maybe a new IEEE80211_TX_CTL_ or IEEE80211_TX_RC_ flag will also be
> needed, so Radiotap can indicate whether rate_control_get_rate needs
> to be called.
ok, I am resending the patch. I included a new flag called
IEEE80211_TX_CTL_RATE_RADIOTAP to indicate if the rate has
been set in the radiotap header. If not, then the rate control
algorithm is called.
Note that in the future there must be other flags like this to
indicate if other parameters, such as power, was also set in
the radiotap header.
Signed-off-by: Rafael Laufer <rlaufer@cs.ucla.edu>
---
Implementation of the IEEE80211_RADIOTAP_RATE
option when parsing radiotap headers to allow
rate selection on a per-packet basis. A new
flag IEEE80211_TX_CTL_RATE_RADIOTAP is also
included to indicate that the rate was set in
the radiotap header and therefore the rate
control algorithm should not change it.
include/net/mac80211.h | 4 ++++
net/mac80211/tx.c | 22 +++++++++++++++++++++-
2 files changed, 25 insertions(+), 1 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index aac84d7..819b01e 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -272,6 +272,9 @@ struct ieee80211_bss_conf {
* transmit function after the current frame, this can be used
* by drivers to kick the DMA queue only if unset or when the
* queue gets full.
+ * @IEEE80211_TX_CTL_RATE_RADIOTAP: completely internal to mac80211,
+ * used to indicate that the rate was defined in the received radiotap
+ * header and therefore the rate control algorithm should not change it.
*/
enum mac80211_tx_control_flags {
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
@@ -293,6 +296,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17),
IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
+ IEEE80211_TX_CTL_RATE_RADIOTAP = BIT(19),
};
/**
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 10a1099..f675844 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -549,7 +549,12 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
* If we're associated with the sta at this point we know we can at
* least send the frame at the lowest bit rate.
*/
- rate_control_get_rate(tx->sdata, tx->sta, &txrc);
+
+ /* In monitor mode, if the IEEE80211_RADIOTAP_RATE option is set in
+ * the received radiotap header, do not call the rate control algorithm.
+ */
+ if (likely(!(info->flags & IEEE80211_TX_CTL_RATE_RADIOTAP)))
+ rate_control_get_rate(tx->sdata, tx->sta, &txrc);
if (unlikely(info->control.rates[0].idx < 0))
return TX_DROP;
@@ -972,6 +977,21 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
tx->flags |= IEEE80211_TX_FRAGMENTED;
break;
+ /* Get the rate parameter from the radiotap header,
+ * allowing rate selection on a per-packet basis
+ */
+ case IEEE80211_RADIOTAP_RATE:
+ bitrate = (*iterator.this_arg) * 5;
+ for (i = 0; i < sband->n_bitrates; i++) {
+ if (sband->bitrates[i].bitrate == bitrate)
+ break;
+ }
+ if (i != sband->n_bitrates) {
+ info->control.rates[0].idx = i;
+ info->flags |= IEEE80211_TX_CTL_RATE_RADIOTAP;
+ }
+ break;
+
/*
* Please update the file
* Documentation/networking/mac80211-injection.txt
--
1.6.0.4
^ permalink raw reply related
* Re: [PATCH] iwlwifi: Make injection of non-broadcast frames work again
From: Gábor Stefanik @ 2009-08-21 18:10 UTC (permalink / raw)
To: reinette chatre
Cc: John Linville, Zhu, Yi, Guy, Wey-Yi W, Rafael Laufer,
ipw3945-devel, linux-wireless
In-Reply-To: <1250877589.30019.14474.camel@rc-desk>
2009/8/21 reinette chatre <reinette.chatre@intel.com>:
> Hi Gábor,
>
> On Fri, 2009-08-21 at 10:24 -0700, Gábor Stefanik wrote:
>
>> For some odd reason, reverting Wei-Yi Guy's patch makes the bug go
>> away
>
> ah - now I see. The driver defaulted to monitor mode in iwl_mac_start.
> This is not correct and this patch rightly removed that code.
>
>> ... should we do that instead for 2.6.31? (I'm all for it, if this
>> patch is not the right thing to do, as Wey-Yi's patch was not a bug
>> fix, just a cleanup.)
>
> No, this patch was more than code cleanup - it changed the driver to
> behave correctly wrt monitor interface type. Unfortunately the
> workaround to get packet injection working was not apparent enough and
> was missed.
>
>
>> My guess is that the "default to MONITOR mode"
>> change is the culprit.
>
> yeah ...
>
>
>> Maybe we should check info->flags & IEEE80211_TX_CTL_INJECTED
>> instead... is there a way to access the ieee80211_tx_info structure
>> from this function (e.g. through priv)?
>
> No, but it may not be necessary. Why is is necessary to call this
> function in the first place if you know this is an injection packet?
> Specifically, in iwl_tx_skb and iwl3945_tx_skb (where ieee80211_tx_info)
> is known) there could just be a test if this is an injected packet, if
> it is, then do not call iwl_get_sta_id, but just use "bcast_sta_id"
> directly. Would this work? Is a test for monitor mode still needed in
> this case?
That can be done, yes. It is also a good idea to convert
iwl_is_monitor_mode(priv) calls with TX_CTL_INJECTED checks, as
mac80211 will set IEEE80211_TX_CTL_INJECTED if and only if the packet
arrived from a monitor interface. (However, when I submitted the first
patches to iwlwifi to enable injection, they were rejected
specifically because I checked INJECTED in iwl_tx_skb/iwl394_tx_skb,
rather than adding a monitor mode case to iwl_get_sta_id... times
change I guess.) I'll submit a patch for this.
>
> Reinette
>
>
>
--
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
^ permalink raw reply
* Re: [PATCH] iwlwifi: Make injection of non-broadcast frames work again
From: reinette chatre @ 2009-08-21 18:24 UTC (permalink / raw)
To: Gábor Stefanik
Cc: John Linville, Zhu, Yi, Guy, Wey-Yi W, Rafael Laufer,
ipw3945-devel, linux-wireless
In-Reply-To: <69e28c910908211110h5a326f4cw7e21cc424bc5fbdc@mail.gmail.com>
Hi Gábor,
On Fri, 2009-08-21 at 11:10 -0700, Gábor Stefanik wrote:
> That can be done, yes. It is also a good idea to convert
> iwl_is_monitor_mode(priv) calls with TX_CTL_INJECTED checks, as
> mac80211 will set IEEE80211_TX_CTL_INJECTED if and only if the packet
> arrived from a monitor interface.
I don't think that is the intention of that function.
iwl_is_monitor_mode() needs to return whether the interface is in
monitor mode or not and being in monitor mode is specifically when some
filter flags are set up. This is what is tested in this function.
> (However, when I submitted the first
> patches to iwlwifi to enable injection, they were rejected
> specifically because I checked INJECTED in iwl_tx_skb/iwl394_tx_skb,
> rather than adding a monitor mode case to iwl_get_sta_id... times
> change I guess.) I'll submit a patch for this.
Sure - you can move the check to iwl_get_sta_id. You will need to
indicate to that function that the frame is being injected.
Reinette
^ permalink raw reply
* Re: [PATCH] iwlwifi: Make injection of non-broadcast frames work again
From: Gábor Stefanik @ 2009-08-21 18:37 UTC (permalink / raw)
To: reinette chatre
Cc: John Linville, Zhu, Yi, Guy, Wey-Yi W, Rafael Laufer,
ipw3945-devel, linux-wireless
In-Reply-To: <1250879069.30019.14482.camel@rc-desk>
2009/8/21 reinette chatre <reinette.chatre@intel.com>:
> Hi Gábor,
>
> On Fri, 2009-08-21 at 11:10 -0700, Gábor Stefanik wrote:
>
>> That can be done, yes. It is also a good idea to convert
>> iwl_is_monitor_mode(priv) calls with TX_CTL_INJECTED checks, as
>> mac80211 will set IEEE80211_TX_CTL_INJECTED if and only if the packet
>> arrived from a monitor interface.
>
> I don't think that is the intention of that function.
> iwl_is_monitor_mode() needs to return whether the interface is in
> monitor mode or not and being in monitor mode is specifically when some
> filter flags are set up. This is what is tested in this function.
Thanks for the clarification. Will submit a corrected patch soon.
>
>> (However, when I submitted the first
>> patches to iwlwifi to enable injection, they were rejected
>> specifically because I checked INJECTED in iwl_tx_skb/iwl394_tx_skb,
>> rather than adding a monitor mode case to iwl_get_sta_id... times
>> change I guess.) I'll submit a patch for this.
>
> Sure - you can move the check to iwl_get_sta_id. You will need to
> indicate to that function that the frame is being injected.
>
> Reinette
>
>
>
>
>
>
--
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
^ permalink raw reply
* [PATCH v2] iwlwifi: Make injection of non-broadcast frames work again
From: Gábor Stefanik @ 2009-08-21 18:44 UTC (permalink / raw)
To: John Linville, Reinette Chatre, Zhu Yi
Cc: Wey-Yi Guy, Rafael Laufer, ipw3945-devel, linux-wireless
Commit 1ccb84d87d04df3c76cd4352fe69786d8c7cf016 by Wey-Yi Guy
("iwlwifi: clean up unused NL80211_IFTYPE_MONITOR for Monitor mode")
broke injection of non-broadcast frames to unassociated stations
(causing a SYSASSERT for all such injected frames), due to injected
frames no longer automatically getting a broadcast station ID assigned.
This patch restores the old behavior, fixing the aforementioned
regression.
Also, consistently check for IEEE80211_TX_CTL_INJECTED instead of
iwl_is_monitor_mode in the TX path, as TX_CTL_INJECTED specifically
means that a given packet is coming from a monitor interface, while
iwl_is_monitor_mode only shows whether a monitor interface exists
on the device.
Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
V2: Use a totally new approach to fixing this bug.
Also fix a few more cases where iwl_is_monitor_mode was incorrectly
used to check whether a given packet comes from a monitor interface.
(For that, IEEE80211_TX_CTL_INJECTED should be used.)
drivers/net/wireless/iwlwifi/iwl-tx.c | 10 ++++++----
drivers/net/wireless/iwlwifi/iwl3945-base.c | 9 ++++++---
2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 9b76bd4..8eba9e9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -718,10 +718,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
#endif
- /* drop all data frame if we are not associated */
+ /* drop all non-injected data frame if we are not associated */
if (ieee80211_is_data(fc) &&
- (!iwl_is_monitor_mode(priv) ||
- !(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */
+ !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
(!iwl_is_associated(priv) ||
((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) ||
!priv->assoc_station_added)) {
@@ -732,7 +731,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr_len = ieee80211_hdrlen(fc);
/* Find (or create) index into station table for destination station */
- sta_id = iwl_get_sta_id(priv, hdr);
+ if (info->flags & IEEE80211_TX_CTL_INJECTED)
+ sta_id = priv->hw_params.bcast_sta_id;
+ else
+ sta_id = iwl_get_sta_id(priv, hdr);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index e617411..d0debdf 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -518,9 +518,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
#endif
- /* drop all data frame if we are not associated */
+ /* drop all non-injected data frame if we are not associated */
if (ieee80211_is_data(fc) &&
- (!iwl_is_monitor_mode(priv)) && /* packet injection */
+ !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
(!iwl_is_associated(priv) ||
((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
@@ -532,7 +532,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr_len = ieee80211_hdrlen(fc);
/* Find (or create) index into station table for destination station */
- sta_id = iwl_get_sta_id(priv, hdr);
+ if (info->flags & IEEE80211_TX_CTL_INJECTED)
+ sta_id = priv->hw_params.bcast_sta_id;
+ else
+ sta_id = iwl_get_sta_id(priv, hdr);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1);
--
1.6.2.4
^ permalink raw reply related
* Re: [PATCH] Implementation of the IEEE80211_RADIOTAP_RATE option
From: Gábor Stefanik @ 2009-08-21 18:52 UTC (permalink / raw)
To: Rafael Laufer; +Cc: Johannes Berg, linux-wireless
In-Reply-To: <4A8EE182.6040709@cs.ucla.edu>
2009/8/21 Rafael Laufer <rlaufer@cs.ucla.edu>:
> Gábor Stefanik wrote:
>>
>> Maybe a new IEEE80211_TX_CTL_ or IEEE80211_TX_RC_ flag will also be
>> needed, so Radiotap can indicate whether rate_control_get_rate needs
>> to be called.
>
> ok, I am resending the patch. I included a new flag called
> IEEE80211_TX_CTL_RATE_RADIOTAP to indicate if the rate has
> been set in the radiotap header. If not, then the rate control
> algorithm is called.
Isn't it easier to check whether we already have a rate configured?
(info->control.rates[0].idx is set to an invalid value before the
rate_control_get_rate call AFAIK, unless you set it in the radiotap
decoding function before.)
>
> Note that in the future there must be other flags like this to
> indicate if other parameters, such as power, was also set in
> the radiotap header.
>
>
> Signed-off-by: Rafael Laufer <rlaufer@cs.ucla.edu>
> ---
> Implementation of the IEEE80211_RADIOTAP_RATE
> option when parsing radiotap headers to allow
> rate selection on a per-packet basis. A new
> flag IEEE80211_TX_CTL_RATE_RADIOTAP is also
> included to indicate that the rate was set in
> the radiotap header and therefore the rate
> control algorithm should not change it.
>
> include/net/mac80211.h | 4 ++++
> net/mac80211/tx.c | 22 +++++++++++++++++++++-
> 2 files changed, 25 insertions(+), 1 deletions(-)
>
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index aac84d7..819b01e 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -272,6 +272,9 @@ struct ieee80211_bss_conf {
> * transmit function after the current frame, this can be used
> * by drivers to kick the DMA queue only if unset or when the
> * queue gets full.
> + * @IEEE80211_TX_CTL_RATE_RADIOTAP: completely internal to mac80211,
> + * used to indicate that the rate was defined in the received radiotap
> + * header and therefore the rate control algorithm should not change it.
> */
> enum mac80211_tx_control_flags {
> IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
> @@ -293,6 +296,7 @@ enum mac80211_tx_control_flags {
> IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
> IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17),
> IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
> + IEEE80211_TX_CTL_RATE_RADIOTAP = BIT(19),
> };
>
> /**
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> index 10a1099..f675844 100644
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -549,7 +549,12 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
> * If we're associated with the sta at this point we know we can at
> * least send the frame at the lowest bit rate.
> */
> - rate_control_get_rate(tx->sdata, tx->sta, &txrc);
> +
> + /* In monitor mode, if the IEEE80211_RADIOTAP_RATE option is set in
> + * the received radiotap header, do not call the rate control algorithm.
> + */
> + if (likely(!(info->flags & IEEE80211_TX_CTL_RATE_RADIOTAP)))
> + rate_control_get_rate(tx->sdata, tx->sta, &txrc);
>
> if (unlikely(info->control.rates[0].idx < 0))
> return TX_DROP;
> @@ -972,6 +977,21 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
> tx->flags |= IEEE80211_TX_FRAGMENTED;
> break;
>
> + /* Get the rate parameter from the radiotap header,
> + * allowing rate selection on a per-packet basis
> + */
> + case IEEE80211_RADIOTAP_RATE:
> + bitrate = (*iterator.this_arg) * 5;
> + for (i = 0; i < sband->n_bitrates; i++) {
> + if (sband->bitrates[i].bitrate == bitrate)
> + break;
> + }
> + if (i != sband->n_bitrates) {
> + info->control.rates[0].idx = i;
> + info->flags |= IEEE80211_TX_CTL_RATE_RADIOTAP;
> + }
> + break;
> +
> /*
> * Please update the file
> * Documentation/networking/mac80211-injection.txt
> --
> 1.6.0.4
>
>
--
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
^ permalink raw reply
* Re: [PATCH] Implementation of the IEEE80211_RADIOTAP_RATE option
From: Rafael Laufer @ 2009-08-21 19:06 UTC (permalink / raw)
To: Gábor Stefanik; +Cc: Johannes Berg, linux-wireless
In-Reply-To: <69e28c910908211152k4423d098i92b25078139ee827@mail.gmail.com>
Gábor Stefanik wrote:
> 2009/8/21 Rafael Laufer <rlaufer@cs.ucla.edu>:
>
>> Gábor Stefanik wrote:
>>
>>> Maybe a new IEEE80211_TX_CTL_ or IEEE80211_TX_RC_ flag will also be
>>> needed, so Radiotap can indicate whether rate_control_get_rate needs
>>> to be called.
>>>
>> ok, I am resending the patch. I included a new flag called
>> IEEE80211_TX_CTL_RATE_RADIOTAP to indicate if the rate has
>> been set in the radiotap header. If not, then the rate control
>> algorithm is called.
>>
>
> Isn't it easier to check whether we already have a rate configured?
> (info->control.rates[0].idx is set to an invalid value before the
> rate_control_get_rate call AFAIK, unless you set it in the radiotap
> decoding function before.)
>
I guess it is also possible, but in that case you rely on the assumption
that the rate is invalid before rate_control_get_rate(). If in the
future this assumption does not hold, the code will break. If, however,
this is always gonna be true, I can change the code to use your
suggestion. Personally, I prefer to use another flag so that future
changes do not affect this code, but let me know what is best.
Rafael
^ permalink raw reply
* Re: [PATCH] Implementation of the IEEE80211_RADIOTAP_RATE option
From: Gábor Stefanik @ 2009-08-21 19:57 UTC (permalink / raw)
To: Rafael Laufer; +Cc: Johannes Berg, linux-wireless
In-Reply-To: <4A8EF031.4050604@cs.ucla.edu>
2009/8/21 Rafael Laufer <rlaufer@cs.ucla.edu>:
> Gábor Stefanik wrote:
>> 2009/8/21 Rafael Laufer <rlaufer@cs.ucla.edu>:
>>
>>> Gábor Stefanik wrote:
>>>
>>>> Maybe a new IEEE80211_TX_CTL_ or IEEE80211_TX_RC_ flag will also be
>>>> needed, so Radiotap can indicate whether rate_control_get_rate needs
>>>> to be called.
>>>>
>>> ok, I am resending the patch. I included a new flag called
>>> IEEE80211_TX_CTL_RATE_RADIOTAP to indicate if the rate has
>>> been set in the radiotap header. If not, then the rate control
>>> algorithm is called.
>>>
>>
>> Isn't it easier to check whether we already have a rate configured?
>> (info->control.rates[0].idx is set to an invalid value before the
>> rate_control_get_rate call AFAIK, unless you set it in the radiotap
>> decoding function before.)
>>
>
> I guess it is also possible, but in that case you rely on the assumption
> that the rate is invalid before rate_control_get_rate(). If in the
> future this assumption does not hold, the code will break. If, however,
> this is always gonna be true, I can change the code to use your
> suggestion. Personally, I prefer to use another flag so that future
> changes do not affect this code, but let me know what is best.
>
> Rafael
>
Actually, that's a good point.
One thing to watch out for is that the actual rate index is not the
only thing the rate controller sets - it is also responsible for
things like retry count & RTS/CTS usage. Those are controlled by other
radiotap fields. So, if any of these values is unset in radiotap, you
will need to call rate control for them, or auto-generate them in
other ways. Otherwise you may end up with e.g. an incorrect retry
count.
--
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
^ permalink raw reply
* Re: pull request: wireless-next-2.6 2009-08-20
From: David Miller @ 2009-08-21 20:12 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20090820172611.GE2657@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Thu, 20 Aug 2009 13:26:11 -0400
> The relentless march of wireless patches for 2.6.32 continues... In
> this batch, further implementation of the LP-PHY support for b43 along
> with the usual batches of driver updates and the like -- iwlwifi, ath9k,
> rt2x00, mwl8k, and others.
>
> Please let me know if there are problems!
Pulled and pushed back out to kernel.org, thanks!
^ permalink raw reply
* Re: pull request: wireless-2.6 2009-08-21
From: David Miller @ 2009-08-21 20:13 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20090821170324.GC8532@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Fri, 21 Aug 2009 13:03:25 -0400
> One more straggler for 2.6.31...without this rtl8187b devices simply
> don't work. :-(
>
> The patch is small and isolated to rtl8187. I think we should take
> it for 2.6.31.
>
> Please let me know if there are problems!
Pulled, and I'll push out to kernel.org after a test build.
Thanks!
^ permalink raw reply
* Re: [PATCH] Implementation of the IEEE80211_RADIOTAP_RATE option
From: Rafael Laufer @ 2009-08-21 20:21 UTC (permalink / raw)
To: Gábor Stefanik; +Cc: Johannes Berg, linux-wireless
In-Reply-To: <69e28c910908211257p748e8be5w6078e7e98a205ef6@mail.gmail.com>
Gábor Stefanik wrote:
> 2009/8/21 Rafael Laufer <rlaufer@cs.ucla.edu>:
>
>> Gábor Stefanik wrote:
>>
>>> 2009/8/21 Rafael Laufer <rlaufer@cs.ucla.edu>:
>>>
>>>
>>>> Gábor Stefanik wrote:
>>>>
>>>>
>>>>> Maybe a new IEEE80211_TX_CTL_ or IEEE80211_TX_RC_ flag will also be
>>>>> needed, so Radiotap can indicate whether rate_control_get_rate needs
>>>>> to be called.
>>>>>
>>>>>
>>>> ok, I am resending the patch. I included a new flag called
>>>> IEEE80211_TX_CTL_RATE_RADIOTAP to indicate if the rate has
>>>> been set in the radiotap header. If not, then the rate control
>>>> algorithm is called.
>>>>
>>>>
>>> Isn't it easier to check whether we already have a rate configured?
>>> (info->control.rates[0].idx is set to an invalid value before the
>>> rate_control_get_rate call AFAIK, unless you set it in the radiotap
>>> decoding function before.)
>>>
>>>
>> I guess it is also possible, but in that case you rely on the assumption
>> that the rate is invalid before rate_control_get_rate(). If in the
>> future this assumption does not hold, the code will break. If, however,
>> this is always gonna be true, I can change the code to use your
>> suggestion. Personally, I prefer to use another flag so that future
>> changes do not affect this code, but let me know what is best.
>>
>> Rafael
>>
>>
>
> Actually, that's a good point.
>
> One thing to watch out for is that the actual rate index is not the
> only thing the rate controller sets - it is also responsible for
> things like retry count & RTS/CTS usage. Those are controlled by other
> radiotap fields. So, if any of these values is unset in radiotap, you
> will need to call rate control for them, or auto-generate them in
> other ways. Otherwise you may end up with e.g. an incorrect retry
> count.
>
>
This is a good point. Where is this done? Is it in the driver-specific
function?
ref->ops <http://localhost/lxr/http/ident?v=2.6.31-rc3;i=ops>->get_rate(ref->priv <http://localhost/lxr/http/ident?v=2.6.31-rc3;i=priv>, ista, priv_sta, txrc);
It is strange that a function called "get_rate" would also change other
fields which are at first sight do not look related to rate. Why not
call other functions for that? What is the reasoning behind this?
Different rates have different retry counts or RTS/CTS usage?
As far as I could tell from a quick look in the code,
rate_control_get_rate only sets the fields of info->control.rates,
except for this driver-specific function.
If this function really does other stuff, then a simple solution is to
check if the IEEE80211_TX_CTL_RATE_RADIOTAP flag is set and, in that
case, store the value of info->control.rates[0].idx before calling
rate_control_get_rate, and restoring it afterwards. Make sense?
Rafael
^ permalink raw reply
* Re: [PATCH] Implementation of the IEEE80211_RADIOTAP_RATE option
From: Rafael Laufer @ 2009-08-21 20:24 UTC (permalink / raw)
To: Gábor Stefanik; +Cc: Johannes Berg, linux-wireless
In-Reply-To: <4A8F01B8.40708@cs.ucla.edu>
Rafael Laufer wrote:
> Gábor Stefanik wrote:
>
>> 2009/8/21 Rafael Laufer <rlaufer@cs.ucla.edu>:
>>
>>
>>> Gábor Stefanik wrote:
>>>
>>>
>>>> 2009/8/21 Rafael Laufer <rlaufer@cs.ucla.edu>:
>>>>
>>>>
>>>>
>>>>> Gábor Stefanik wrote:
>>>>>
>>>>>
>>>>>
>>>>>> Maybe a new IEEE80211_TX_CTL_ or IEEE80211_TX_RC_ flag will also be
>>>>>> needed, so Radiotap can indicate whether rate_control_get_rate needs
>>>>>> to be called.
>>>>>>
>>>>>>
>>>>>>
>>>>> ok, I am resending the patch. I included a new flag called
>>>>> IEEE80211_TX_CTL_RATE_RADIOTAP to indicate if the rate has
>>>>> been set in the radiotap header. If not, then the rate control
>>>>> algorithm is called.
>>>>>
>>>>>
>>>>>
>>>> Isn't it easier to check whether we already have a rate configured?
>>>> (info->control.rates[0].idx is set to an invalid value before the
>>>> rate_control_get_rate call AFAIK, unless you set it in the radiotap
>>>> decoding function before.)
>>>>
>>>>
>>>>
>>> I guess it is also possible, but in that case you rely on the assumption
>>> that the rate is invalid before rate_control_get_rate(). If in the
>>> future this assumption does not hold, the code will break. If, however,
>>> this is always gonna be true, I can change the code to use your
>>> suggestion. Personally, I prefer to use another flag so that future
>>> changes do not affect this code, but let me know what is best.
>>>
>>> Rafael
>>>
>>>
>>>
>> Actually, that's a good point.
>>
>> One thing to watch out for is that the actual rate index is not the
>> only thing the rate controller sets - it is also responsible for
>> things like retry count & RTS/CTS usage. Those are controlled by other
>> radiotap fields. So, if any of these values is unset in radiotap, you
>> will need to call rate control for them, or auto-generate them in
>> other ways. Otherwise you may end up with e.g. an incorrect retry
>> count.
>>
>>
>>
> This is a good point. Where is this done? Is it in the driver-specific
> function?
>
> ref->ops <http://localhost/lxr/http/ident?v=2.6.31-rc3;i=ops>->get_rate(ref->priv <http://localhost/lxr/http/ident?v=2.6.31-rc3;i=priv>, ista, priv_sta, txrc);
>
>
> It is strange that a function called "get_rate" would also change other
> fields which are at first sight do not look related to rate. Why not
> call other functions for that? What is the reasoning behind this?
> Different rates have different retry counts or RTS/CTS usage?
>
> As far as I could tell from a quick look in the code,
> rate_control_get_rate only sets the fields of info->control.rates,
> except for this driver-specific function.
>
> If this function really does other stuff, then a simple solution is to
> check if the IEEE80211_TX_CTL_RATE_RADIOTAP flag is set and, in that
> case, store the value of info->control.rates[0].idx before calling
> rate_control_get_rate, and restoring it afterwards. Make sense?
>
ops, I meant
ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
^ permalink raw reply
* [PATCH 01/14] iwlwifi: set default tx power user limit to minimal
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Set the tx_power_user_lmt to the lowest power level
this value will get overwritten by channel's max power avg
from eeprom
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index f1f6dab..43781dc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1671,7 +1671,10 @@ int iwl_init_drv(struct iwl_priv *priv)
priv->qos_data.qos_cap.val = 0;
priv->rates_mask = IWL_RATES_MASK;
- priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX;
+ /* Set the tx_power_user_lmt to the lowest power level
+ * this value will get overwritten by channel max power avg
+ * from eeprom */
+ priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN;
ret = iwl_init_channel_map(priv);
if (ret) {
--
1.5.6.3
^ permalink raw reply related
* [PATCH 03/14] iwlwifi: name changes from "tx_power_channel_lmt" to "tx_power_device_lmt"
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Changing the name from "tx_power_channel_lmt" to "tx_power_device_lmt";
to give idea that scope of limit is for overall device, not any
individual channels
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++++----
drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index faafcae..82dadd0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -543,8 +543,8 @@ int iwlcore_init_geos(struct iwl_priv *priv)
geo_ch->flags |= ch->ht40_extension_channel;
- if (ch->max_power_avg > priv->tx_power_channel_lmt)
- priv->tx_power_channel_lmt = ch->max_power_avg;
+ if (ch->max_power_avg > priv->tx_power_device_lmt)
+ priv->tx_power_device_lmt = ch->max_power_avg;
} else {
geo_ch->flags |= IEEE80211_CHAN_DISABLED;
}
@@ -1708,10 +1708,10 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
return -EINVAL;
}
- if (tx_power > priv->tx_power_channel_lmt) {
+ if (tx_power > priv->tx_power_device_lmt) {
IWL_WARN(priv,
"Requested user TXPOWER %d above upper limit %d.\n",
- tx_power, priv->tx_power_channel_lmt);
+ tx_power, priv->tx_power_device_lmt);
return -EINVAL;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 0178734..ccea2e4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1215,7 +1215,7 @@ struct iwl_priv {
/* TX Power */
s8 tx_power_user_lmt;
- s8 tx_power_channel_lmt;
+ s8 tx_power_device_lmt;
#ifdef CONFIG_IWLWIFI_DEBUG
--
1.5.6.3
^ permalink raw reply related
* [PATCH 05/14] iwlwifi: change IWL6000_UCODE_API_MAX to v4
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
uCode version changed to v4 for 6000 series
The additional parameter added to v4 is providing current tx power for
each chain in tx statistics portion of "statistics notification"
command.
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ++--
drivers/net/wireless/iwlwifi/iwl-commands.h | 18 ++++++++++++++++--
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 383177d..33ef736 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -46,8 +46,8 @@
#include "iwl-5000-hw.h"
/* Highest firmware API version supported */
-#define IWL6000_UCODE_API_MAX 3
-#define IWL6050_UCODE_API_MAX 3
+#define IWL6000_UCODE_API_MAX 4
+#define IWL6050_UCODE_API_MAX 4
/* Lowest firmware API version supported */
#define IWL6000_UCODE_API_MIN 1
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index f430384..6b82d4e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2930,6 +2930,20 @@ struct statistics_rx {
struct statistics_rx_ht_phy ofdm_ht;
} __attribute__ ((packed));
+/**
+ * struct statistics_tx_power - current tx power
+ *
+ * @ant_a: current tx power on chain a in 1/2 dB step
+ * @ant_b: current tx power on chain b in 1/2 dB step
+ * @ant_c: current tx power on chain c in 1/2 dB step
+ */
+struct statistics_tx_power {
+ u8 ant_a;
+ u8 ant_b;
+ u8 ant_c;
+ u8 reserved;
+} __attribute__ ((packed));
+
struct statistics_tx_non_phy_agg {
__le32 ba_timeout;
__le32 ba_reschedule_frames;
@@ -2941,8 +2955,6 @@ struct statistics_tx_non_phy_agg {
__le32 underrun;
__le32 bt_prio_kill;
__le32 rx_ba_rsp_cnt;
- __le32 reserved2;
- __le32 reserved3;
} __attribute__ ((packed));
struct statistics_tx {
@@ -2961,6 +2973,8 @@ struct statistics_tx {
__le32 cts_timeout_collision;
__le32 ack_or_ba_timeout_collision;
struct statistics_tx_non_phy_agg agg;
+ struct statistics_tx_power tx_power;
+ __le32 reserved1;
} __attribute__ ((packed));
--
1.5.6.3
^ permalink raw reply related
* [PATCH 0/14] iwlwifi and ipw2x00 driver updates
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Reinette Chatre
We include a few fixes surrounding TX power. We support enhanced TX power
information provided by newer hardware. The fixes to HT continue. We also
include two general bugfixes: fix error when bringing interface down
that has hardware key set and cancelling scan when bringing interface
down.
We also include two administrative patches to ipw2x00 to update maintenance
status and contact information.
[PATCH 01/14] iwlwifi: set default tx power user limit to minimal
[PATCH 02/14] iwlwifi: do not allow set tx power over channel power limit
[PATCH 03/14] iwlwifi: name changes from "tx_power_channel_lmt" to "tx_power_device_lmt"
[PATCH 04/14] iwlwifi: error checking for setting tx_power in sysfs
[PATCH 05/14] iwlwifi: change IWL6000_UCODE_API_MAX to v4
[PATCH 06/14] iwlwifi: show current tx power
[PATCH 07/14] iwlwifi: clear rate control flags on non-HT packet
[PATCH 08/14] iwlwifi: set HT flags in ieee80211_rx_status for received packets
[PATCH 09/14] iwlwifi: remove duplicated define
[PATCH 10/14] iwlwifi: read enhanced tx power info from EEPROM image
[PATCH 11/14] iwlwifi: fix remove key error
[PATCH 12/14] iwlwifi: fix unloading driver while scanning
[PATCH 13/14] ipw2x00: update contact information
[PATCH 14/14] MAINTAINERS: Update ipw2x00 and iwlwifi entries
Thank you
Reinette
^ permalink raw reply
* [PATCH 04/14] iwlwifi: error checking for setting tx_power in sysfs
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Perform error checking and report failure when setting tx power from
sysfs.
If fail to set the tx power, do not update the local copy, so user will
not see the incorrect tx power in sysfs
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-agn.c | 13 +++++++++----
drivers/net/wireless/iwlwifi/iwl-core.c | 28 +++++++++++++++++++++-------
2 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 2232b17..533b393 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2477,10 +2477,15 @@ static ssize_t store_tx_power(struct device *d,
ret = strict_strtoul(buf, 10, &val);
if (ret)
IWL_INFO(priv, "%s is not in decimal form.\n", buf);
- else
- iwl_set_tx_power(priv, val, false);
-
- return count;
+ else {
+ ret = iwl_set_tx_power(priv, val, false);
+ if (ret)
+ IWL_ERR(priv, "failed setting tx power (0x%d).\n",
+ ret);
+ else
+ ret = count;
+ }
+ return ret;
}
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 82dadd0..c62c081 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1701,6 +1701,8 @@ EXPORT_SYMBOL(iwl_init_drv);
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
{
int ret = 0;
+ s8 prev_tx_power = priv->tx_power_user_lmt;
+
if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) {
IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n",
tx_power,
@@ -1718,15 +1720,27 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
if (priv->tx_power_user_lmt != tx_power)
force = true;
- priv->tx_power_user_lmt = tx_power;
-
/* if nic is not up don't send command */
- if (!iwl_is_ready_rf(priv))
- return ret;
-
- if (force && priv->cfg->ops->lib->send_tx_power)
- ret = priv->cfg->ops->lib->send_tx_power(priv);
+ if (iwl_is_ready_rf(priv)) {
+ priv->tx_power_user_lmt = tx_power;
+ if (force && priv->cfg->ops->lib->send_tx_power)
+ ret = priv->cfg->ops->lib->send_tx_power(priv);
+ else if (!priv->cfg->ops->lib->send_tx_power)
+ ret = -EOPNOTSUPP;
+ /*
+ * if fail to set tx_power, restore the orig. tx power
+ */
+ if (ret)
+ priv->tx_power_user_lmt = prev_tx_power;
+ }
+ /*
+ * Even this is an async host command, the command
+ * will always report success from uCode
+ * So once driver can placing the command into the queue
+ * successfully, driver can use priv->tx_power_user_lmt
+ * to reflect the current tx power
+ */
return ret;
}
EXPORT_SYMBOL(iwl_set_tx_power);
--
1.5.6.3
^ permalink raw reply related
* [PATCH 09/14] iwlwifi: remove duplicated define
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Remove duplicated define "STA_FLG_PWR_SAVE_MSK"
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-commands.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 6b82d4e..2c5c88f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -886,7 +886,6 @@ struct iwl_qosparam_cmd {
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2);
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8);
-#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8);
#define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17)
#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18)
#define STA_FLG_MAX_AGG_SIZE_POS (19)
--
1.5.6.3
^ permalink raw reply related
* [PATCH 07/14] iwlwifi: clear rate control flags on non-HT packet
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Daniel C Halperin, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Daniel C Halperin <daniel.c.halperin@intel.com>
Clear the flags (most importantly, the IEEE80211_TX_RC_MCS flag)
when sending a non-HT packet so that the rate index can be properly treated.
This fixes the reporting of legacy rates in wireless-extensions for packets
sent after an HT packet.
Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index fee110d..26ec969 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -2546,6 +2546,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
rate_idx = rate_lowest_index(sband, sta);
else if (sband->band == IEEE80211_BAND_5GHZ)
rate_idx -= IWL_FIRST_OFDM_RATE;
+ info->control.rates[0].flags = 0;
}
info->control.rates[0].idx = rate_idx;
--
1.5.6.3
^ permalink raw reply related
* [PATCH 08/14] iwlwifi: set HT flags in ieee80211_rx_status for received packets
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Daniel C Halperin, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Daniel C Halperin <daniel.c.halperin@intel.com>
Add code to set the HT flags (HT, 40 MHz, Short guard interval) in
the ieee80211_rx_status field passed to mac80211. This ensures that mac80211
processes these HT packets correctly.
Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-rx.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 353d9a2..e34d3fc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -915,6 +915,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
u32 len;
u32 ampdu_status;
u16 fc;
+ u32 rate_n_flags;
/**
* REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
@@ -1032,6 +1033,15 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
rx_status.flag |= RX_FLAG_SHORTPRE;
+ /* Set up the HT phy flags */
+ rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
+ if (rate_n_flags & RATE_MCS_HT_MSK)
+ rx_status.flag |= RX_FLAG_HT;
+ if (rate_n_flags & RATE_MCS_HT40_MSK)
+ rx_status.flag |= RX_FLAG_40MHZ;
+ if (rate_n_flags & RATE_MCS_SGI_MSK)
+ rx_status.flag |= RX_FLAG_SHORT_GI;
+
if (iwl_is_network_packet(priv, header)) {
priv->last_rx_rssi = rx_status.signal;
priv->last_beacon_time = priv->ucode_beacon_time;
--
1.5.6.3
^ permalink raw reply related
* [PATCH 02/14] iwlwifi: do not allow set tx power over channel power limit
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
When setting tx power in sysfs, check against max channel tx power
limit instead of IWL_TX_POWER_TARGET_POWER_MAX.
Different devices have different max tx power limit; using
IWL_TX_POWER_TARGET_POWER_MAX can excess the limitaion and give wrong
information.
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 43781dc..faafcae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1708,10 +1708,10 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
return -EINVAL;
}
- if (tx_power > IWL_TX_POWER_TARGET_POWER_MAX) {
- IWL_WARN(priv, "Requested user TXPOWER %d above upper limit %d.\n",
- tx_power,
- IWL_TX_POWER_TARGET_POWER_MAX);
+ if (tx_power > priv->tx_power_channel_lmt) {
+ IWL_WARN(priv,
+ "Requested user TXPOWER %d above upper limit %d.\n",
+ tx_power, priv->tx_power_channel_lmt);
return -EINVAL;
}
--
1.5.6.3
^ permalink raw reply related
* [PATCH 06/14] iwlwifi: show current tx power
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
debugFs file show current tx power for all the transmit chains
Adding "tx_power" file in /sys/kernal/debug/ieee80211/phy0/iwlagn/debug
to display current tx power for all the active chains in 1/2 dB step.
Show tx power information "Not available" if uCode can not provide the
information or interface is down.
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-debug.h | 1 +
drivers/net/wireless/iwlwifi/iwl-debugfs.c | 54 ++++++++++++++++++++++++++++
2 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 723f38a..cbc6290 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -107,6 +107,7 @@ struct iwl_debugfs {
struct dentry *file_ucode_general_stats;
struct dentry *file_sensitivity;
struct dentry *file_chain_noise;
+ struct dentry *file_tx_power;
} dbgfs_debug_files;
u32 sram_offset;
u32 sram_len;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index f68fb47..fb84485 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -1563,6 +1563,57 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
return ret;
}
+static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ char buf[128];
+ int pos = 0;
+ ssize_t ret;
+ const size_t bufsz = sizeof(buf);
+ struct statistics_tx *tx;
+
+ if (!iwl_is_alive(priv))
+ pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
+ else {
+ /* make request to uCode to retrieve statistics information */
+ mutex_lock(&priv->mutex);
+ ret = iwl_send_statistics_request(priv, 0);
+ mutex_unlock(&priv->mutex);
+
+ if (ret) {
+ IWL_ERR(priv, "Error sending statistics request: %zd\n",
+ ret);
+ return -EAGAIN;
+ }
+ tx = &priv->statistics.tx;
+ if (tx->tx_power.ant_a ||
+ tx->tx_power.ant_b ||
+ tx->tx_power.ant_c) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "tx power: (1/2 dB step)\n");
+ if ((priv->cfg->valid_tx_ant & ANT_A) &&
+ tx->tx_power.ant_a)
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tantenna A: 0x%X\n",
+ tx->tx_power.ant_a);
+ if ((priv->cfg->valid_tx_ant & ANT_B) &&
+ tx->tx_power.ant_b)
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tantenna B: 0x%X\n",
+ tx->tx_power.ant_b);
+ if ((priv->cfg->valid_tx_ant & ANT_C) &&
+ tx->tx_power.ant_c)
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tantenna C: 0x%X\n",
+ tx->tx_power.ant_c);
+ } else
+ pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
+ }
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -1573,6 +1624,7 @@ DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
DEBUGFS_READ_FILE_OPS(ucode_general_stats);
DEBUGFS_READ_FILE_OPS(sensitivity);
DEBUGFS_READ_FILE_OPS(chain_noise);
+DEBUGFS_READ_FILE_OPS(tx_power);
/*
* Create the debugfs files and directories
@@ -1621,6 +1673,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(traffic_log, debug);
DEBUGFS_ADD_FILE(rx_queue, debug);
DEBUGFS_ADD_FILE(tx_queue, debug);
+ DEBUGFS_ADD_FILE(tx_power, debug);
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
@@ -1674,6 +1727,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power);
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
file_ucode_rx_stats);
--
1.5.6.3
^ permalink raw reply related
* [PATCH 10/14] iwlwifi: read enhanced tx power info from EEPROM image
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
For 6000 series and up, additional enhanced regulatory tx power
limitation information is added to EEPROM image.
In order to setup the tx power limitation per channel correctly. Read
the enhanced tx power information from EEPROM image and update
accordingly.
The information is provided per SISO (a,b,c) chain based, it also has
information for both MIMO2 and MIMO3. For tx power regulatory
limitation, take the highest number from all the chains and update.
Also update tx_power_user_lmt to the highest power supported by any
channels and chains
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-6000.c | 1 +
drivers/net/wireless/iwlwifi/iwl-eeprom.c | 252 +++++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-eeprom.h | 80 +++++++++-
3 files changed, 332 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 33ef736..82b9c93 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -126,6 +126,7 @@ static struct iwl_lib_ops iwl6000_lib = {
.release_semaphore = iwlcore_eeprom_release_semaphore,
.calib_version = iwl5000_eeprom_calib_version,
.query_addr = iwl5000_eeprom_query_addr,
+ .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
},
.post_associate = iwl_post_associate,
.isr = iwl_isr_ict,
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 01b95e8..3d2b93a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -135,6 +135,78 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
};
+/**
+ * struct iwl_txpwr_section: eeprom section information
+ * @offset: indirect address into eeprom image
+ * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
+ * @band: band type for the section
+ * @is_common - true: common section, false: channel section
+ * @is_cck - true: cck section, false: not cck section
+ * @is_ht_40 - true: all channel in the section are HT40 channel,
+ * false: legacy or HT 20 MHz
+ * ignore if it is common section
+ * @iwl_eeprom_section_channel: channel array in the section,
+ * ignore if common section
+ */
+struct iwl_txpwr_section {
+ u32 offset;
+ u8 count;
+ enum ieee80211_band band;
+ bool is_common;
+ bool is_cck;
+ bool is_ht40;
+ u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
+};
+
+/**
+ * section 1 - 3 are regulatory tx power apply to all channels based on
+ * modulation: CCK, OFDM
+ * Band: 2.4GHz, 5.2GHz
+ * section 4 - 10 are regulatory tx power apply to specified channels
+ * For example:
+ * 1L - Channel 1 Legacy
+ * 1HT - Channel 1 HT
+ * (1,+1) - Channel 1 HT40 "_above_"
+ *
+ * Section 1: all CCK channels
+ * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
+ * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
+ * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
+ * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
+ * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
+ * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
+ * Section 8: 2.4 GHz channel: 13L, 13HT
+ * Section 9: 2.4 GHz channel: 140L, 140HT
+ * Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1)
+ *
+ */
+static const struct iwl_txpwr_section enhinfo[] = {
+ { EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
+ { EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
+ { EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
+ { EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
+ false, false, false,
+ {1, 1, 2, 2, 10, 10, 11, 11 } },
+ { EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
+ false, false, true,
+ { 1, 2, 6, 7, 9 } },
+ { EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
+ false, false, false,
+ { 36, 64, 100, 36, 64, 100 } },
+ { EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
+ false, false, true,
+ { 36, 60, 100 } },
+ { EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
+ false, false, false,
+ { 13, 13 } },
+ { EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
+ false, false, false,
+ { 140, 140 } },
+ { EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
+ false, false, true,
+ { 132, 44 } },
+};
+
/******************************************************************************
*
* EEPROM related functions
@@ -643,6 +715,178 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
return 0;
}
+/**
+ * iwl_get_max_txpower_avg - get the highest tx power from all chains.
+ * find the highest tx power from all chains for the channel
+ */
+static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element)
+{
+ s8 max_txpower_avg = 0; /* (dBm) */
+
+ IWL_DEBUG_INFO(priv, "%d - "
+ "chain_a: %d dB chain_b: %d dB "
+ "chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
+ element,
+ enhanced_txpower[element].chain_a_max >> 1,
+ enhanced_txpower[element].chain_b_max >> 1,
+ enhanced_txpower[element].chain_c_max >> 1,
+ enhanced_txpower[element].mimo2_max >> 1,
+ enhanced_txpower[element].mimo3_max >> 1);
+ /* Take the highest tx power from any valid chains */
+ if ((priv->cfg->valid_tx_ant & ANT_A) &&
+ (enhanced_txpower[element].chain_a_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].chain_a_max;
+ if ((priv->cfg->valid_tx_ant & ANT_B) &&
+ (enhanced_txpower[element].chain_b_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].chain_b_max;
+ if ((priv->cfg->valid_tx_ant & ANT_C) &&
+ (enhanced_txpower[element].chain_c_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].chain_c_max;
+ if (((priv->cfg->valid_tx_ant == ANT_AB) |
+ (priv->cfg->valid_tx_ant == ANT_BC) |
+ (priv->cfg->valid_tx_ant == ANT_AC)) &&
+ (enhanced_txpower[element].mimo2_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].mimo2_max;
+ if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
+ (enhanced_txpower[element].mimo3_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].mimo3_max;
+
+ /* max. tx power in EEPROM is in 1/2 dBm format
+ * convert from 1/2 dBm to dBm
+ */
+ return max_txpower_avg >> 1;
+}
+
+/**
+ * iwl_update_common_txpower: update channel tx power
+ * update tx power per band based on EEPROM enhanced tx power info.
+ */
+static s8 iwl_update_common_txpower(struct iwl_priv *priv,
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+ int section, int element)
+{
+ struct iwl_channel_info *ch_info;
+ int ch;
+ bool is_ht40 = false;
+ s8 max_txpower_avg; /* (dBm) */
+
+ /* it is common section, contain all type (Legacy, HT and HT40)
+ * based on the element in the section to determine
+ * is it HT 40 or not
+ */
+ if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
+ is_ht40 = true;
+ max_txpower_avg =
+ iwl_get_max_txpower_avg(priv, enhanced_txpower, element);
+ ch_info = priv->channel_info;
+
+ for (ch = 0; ch < priv->channel_count; ch++) {
+ /* find matching band and update tx power if needed */
+ if ((ch_info->band == enhinfo[section].band) &&
+ (ch_info->max_power_avg < max_txpower_avg) && (!is_ht40)) {
+ /* Update regulatory-based run-time data */
+ ch_info->max_power_avg = ch_info->curr_txpow =
+ max_txpower_avg;
+ ch_info->scan_power = max_txpower_avg;
+ }
+ if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
+ ch_info->ht40_max_power_avg &&
+ (ch_info->ht40_max_power_avg < max_txpower_avg)) {
+ /* Update regulatory-based run-time data */
+ ch_info->ht40_max_power_avg = max_txpower_avg;
+ ch_info->ht40_curr_txpow = max_txpower_avg;
+ ch_info->ht40_scan_power = max_txpower_avg;
+ }
+ ch_info++;
+ }
+ return max_txpower_avg;
+}
+
+/**
+ * iwl_update_channel_txpower: update channel tx power
+ * update channel tx power based on EEPROM enhanced tx power info.
+ */
+static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+ int section, int element)
+{
+ struct iwl_channel_info *ch_info;
+ int ch;
+ u8 channel;
+ s8 max_txpower_avg; /* (dBm) */
+
+ channel = enhinfo[section].iwl_eeprom_section_channel[element];
+ max_txpower_avg =
+ iwl_get_max_txpower_avg(priv, enhanced_txpower, element);
+
+ ch_info = priv->channel_info;
+ for (ch = 0; ch < priv->channel_count; ch++) {
+ /* find matching channel and update tx power if needed */
+ if (ch_info->channel == channel) {
+ if ((ch_info->max_power_avg < max_txpower_avg) &&
+ (!enhinfo[section].is_ht40)) {
+ /* Update regulatory-based run-time data */
+ ch_info->max_power_avg = max_txpower_avg;
+ ch_info->curr_txpow = max_txpower_avg;
+ ch_info->scan_power = max_txpower_avg;
+ }
+ if ((enhinfo[section].is_ht40) &&
+ (ch_info->ht40_max_power_avg) &&
+ (ch_info->ht40_max_power_avg < max_txpower_avg)) {
+ /* Update regulatory-based run-time data */
+ ch_info->ht40_max_power_avg = max_txpower_avg;
+ ch_info->ht40_curr_txpow = max_txpower_avg;
+ ch_info->ht40_scan_power = max_txpower_avg;
+ }
+ break;
+ }
+ ch_info++;
+ }
+ return max_txpower_avg;
+}
+
+/**
+ * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
+ */
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
+{
+ int eeprom_section_count = 0;
+ int section, element;
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
+ u32 offset;
+ s8 max_txpower_avg; /* (dBm) */
+
+ /* Loop through all the sections
+ * adjust bands and channel's max tx power
+ * Set the tx_power_user_lmt to the highest power
+ * supported by any channels and chains
+ */
+ for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
+ eeprom_section_count = enhinfo[section].count;
+ offset = enhinfo[section].offset;
+ enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
+ iwl_eeprom_query_addr(priv, offset);
+
+ for (element = 0; element < eeprom_section_count; element++) {
+ if (enhinfo[section].is_common)
+ max_txpower_avg =
+ iwl_update_common_txpower(priv,
+ enhanced_txpower, section, element);
+ else
+ max_txpower_avg =
+ iwl_update_channel_txpower(priv,
+ enhanced_txpower, section, element);
+
+ /* Update the tx_power_user_lmt to the highest power
+ * supported by any channel */
+ if (max_txpower_avg > priv->tx_power_user_lmt)
+ priv->tx_power_user_lmt = max_txpower_avg;
+ }
+ }
+}
+EXPORT_SYMBOL(iwlcore_eeprom_enhanced_txpower);
+
#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
? # x " " : "")
@@ -790,6 +1034,14 @@ int iwl_init_channel_map(struct iwl_priv *priv)
}
}
+ /* for newer device (6000 series and up)
+ * EEPROM contain enhanced tx power information
+ * driver need to process addition information
+ * to determine the max channel tx power limits
+ */
+ if (priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower)
+ priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower(priv);
+
return 0;
}
EXPORT_SYMBOL(iwl_init_channel_map);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index ca7920a..6b68db7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -118,6 +118,30 @@ struct iwl_eeprom_channel {
s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
} __attribute__ ((packed));
+/**
+ * iwl_eeprom_enhanced_txpwr structure
+ * This structure presents the enhanced regulatory tx power limit layout
+ * in eeprom image
+ * Enhanced regulatory tx power portion of eeprom image can be broken down
+ * into individual structures; each one is 8 bytes in size and contain the
+ * following information
+ * @chain_a_max_pwr: chain a max power in 1/2 dBm
+ * @chain_b_max_pwr: chain b max power in 1/2 dBm
+ * @chain_c_max_pwr: chain c max power in 1/2 dBm
+ * @mimo2_max_pwr: mimo2 max power in 1/2 dBm
+ * @mimo3_max_pwr: mimo3 max power in 1/2 dBm
+ *
+ */
+struct iwl_eeprom_enhanced_txpwr {
+ u16 reserved;
+ s8 chain_a_max;
+ s8 chain_b_max;
+ s8 chain_c_max;
+ s8 reserved1;
+ s8 mimo2_max;
+ s8 mimo3_max;
+} __attribute__ ((packed));
+
/* 3945 Specific */
#define EEPROM_3945_EEPROM_VERSION (0x2f)
@@ -175,6 +199,59 @@ struct iwl_eeprom_channel {
#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
+/* 6000 and up regulatory tx power - indirect access */
+/* max. elements per section */
+#define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8)
+#define EEPROM_TXPOWER_COMMON_HT40_INDEX (2)
+
+/**
+ * Partition the enhanced tx power portion of eeprom image into
+ * 10 sections based on band, modulation, frequency and channel
+ *
+ * Section 1: all CCK channels
+ * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40 ) channels
+ * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
+ * Section 4: 2.4 GHz 20MHz channels: 1, 2, 10, 11. Both Legacy and HT
+ * Section 5: 2.4 GHz 40MHz channels: 1, 2, 6, 7, 9, (_above_)
+ * Section 6: 5.2 GHz 20MHz channels: 36, 64, 100, both Legacy and HT
+ * Section 7: 5.2 GHz 40MHz channels: 36, 60, 100 (_above_)
+ * Section 8: 2.4 GHz channel 13, Both Legacy and HT
+ * Section 9: 2.4 GHz channel 140, Both Legacy and HT
+ * Section 10: 2.4 GHz 40MHz channels: 132, 44 (_above_)
+ */
+/* 2.4 GHz band: CCK */
+#define EEPROM_LB_CCK_20_COMMON ((0xAA)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 8 bytes */
+/* 2.4 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
+#define EEPROM_LB_OFDM_COMMON ((0xB2)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
+/* 5.2 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
+#define EEPROM_HB_OFDM_COMMON ((0xCA)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
+/* 2.4GHz band channels:
+ * 1Legacy, 1HT, 2Legacy, 2HT, 10Legacy, 10HT, 11Legacy, 11HT */
+#define EEPROM_LB_OFDM_20_BAND ((0xE2)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 64 bytes */
+/* 2.4 GHz band HT40 channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) */
+#define EEPROM_LB_OFDM_HT40_BAND ((0x122)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 40 bytes */
+/* 5.2GHz band channels: 36Legacy, 36HT, 64Legacy, 64HT, 100Legacy, 100HT */
+#define EEPROM_HB_OFDM_20_BAND ((0x14A)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 48 bytes */
+/* 5.2 GHz band HT40 channels: (36,+1) (60,+1) (100,+1) */
+#define EEPROM_HB_OFDM_HT40_BAND ((0x17A)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
+/* 2.4 GHz band, channnel 13: Legacy, HT */
+#define EEPROM_LB_OFDM_20_CHANNEL_13 ((0x192)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */
+/* 5.2 GHz band, channnel 140: Legacy, HT */
+#define EEPROM_HB_OFDM_20_CHANNEL_140 ((0x1A2)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */
+/* 5.2 GHz band, HT40 channnels (132,+1) (44,+1) */
+#define EEPROM_HB_OFDM_HT40_BAND_1 ((0x1B2)\
+ | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */
+
+
/* 5050 Specific */
#define EEPROM_5050_TX_POWER_VERSION (4)
#define EEPROM_5050_EEPROM_VERSION (0x21E)
@@ -389,6 +466,7 @@ struct iwl_eeprom_ops {
void (*release_semaphore) (struct iwl_priv *priv);
u16 (*calib_version) (struct iwl_priv *priv);
const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset);
+ void (*update_enhanced_txpower) (struct iwl_priv *priv);
};
@@ -403,7 +481,7 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
-
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
int iwl_init_channel_map(struct iwl_priv *priv);
void iwl_free_channel_map(struct iwl_priv *priv);
const struct iwl_channel_info *iwl_get_channel_info(
--
1.5.6.3
^ permalink raw reply related
* [PATCH 12/14] iwlwifi: fix unloading driver while scanning
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Wey-Yi Guy, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
If NetworkManager is busy scanning when user
tries to unload the module, the driver can not be unloaded
because HW still scanning.
Make sure driver sends abort scan host command to uCode if it
is in the middle of scanning during driver unload.
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-scan.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 533b393..00457bf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2155,7 +2155,7 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
priv->is_open = 0;
- if (iwl_is_ready_rf(priv)) {
+ if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) {
/* stop mac, cancel any scan request and clear
* RXON_FILTER_ASSOC_MSK BIT
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index c4c916d..4f3a108 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -796,7 +796,8 @@ void iwl_bg_abort_scan(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
- if (!iwl_is_ready(priv))
+ if (!test_bit(STATUS_READY, &priv->status) ||
+ !test_bit(STATUS_GEO_CONFIGURED, &priv->status))
return;
mutex_lock(&priv->mutex);
--
1.5.6.3
^ permalink raw reply related
* [PATCH 11/14] iwlwifi: fix remove key error
From: Reinette Chatre @ 2009-08-21 20:34 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Abhijeet Kolekar, Reinette Chatre
In-Reply-To: <1250886867-4112-1-git-send-email-reinette.chatre@intel.com>
From: Abhijeet Kolekar <abhijeet.kolekar@intel.com>
Fix following error by sending synchronous command and waiting for the command
to complete.
mac80211-phy0: failed to remove key (0, ff:ff:ff:ff:ff:ff) from hardware (-16).
-16 is EBUSY error. The asynchronous command tests for STATUS_EXIT_PENDING
while interface is getting down and it returns -EBUSY error if set.
Changing the host command from asynchronous call to synchronous call
enables command to be run while interface is going down.
Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index c6633fe..a2b9ec8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -520,7 +520,7 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
struct iwl_host_cmd cmd = {
.id = REPLY_WEPKEY,
.data = wep_cmd,
- .flags = CMD_ASYNC,
+ .flags = CMD_SYNC,
};
memset(wep_cmd, 0, cmd_size +
--
1.5.6.3
^ 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