2010-09-23 00:02:01 +08:00
|
|
|
/******************************************************************************
|
|
|
|
*
|
2011-04-06 00:42:00 +08:00
|
|
|
* Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
|
2010-09-23 00:02:01 +08:00
|
|
|
*
|
|
|
|
* Portions of this file are derived from the ipw3945 project, as well
|
|
|
|
* as portions of the ieee80211 subsystem header files.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
|
|
|
*
|
|
|
|
* The full GNU General Public License is included in this distribution in the
|
|
|
|
* file called LICENSE.
|
|
|
|
*
|
|
|
|
* Contact Information:
|
|
|
|
* Intel Linux Wireless <ilw@linux.intel.com>
|
|
|
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include <net/mac80211.h>
|
|
|
|
|
|
|
|
#include "iwl-dev.h"
|
|
|
|
#include "iwl-core.h"
|
|
|
|
#include "iwl-sta.h"
|
|
|
|
#include "iwl-agn.h"
|
2011-07-08 23:46:16 +08:00
|
|
|
#include "iwl-trans.h"
|
2010-09-23 00:02:01 +08:00
|
|
|
|
2011-10-10 22:26:54 +08:00
|
|
|
void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
|
|
|
u8 sta_id, struct iwl_link_quality_cmd *link_cmd)
|
2010-09-23 00:02:01 +08:00
|
|
|
{
|
|
|
|
int i, r;
|
|
|
|
u32 rate_flags = 0;
|
|
|
|
__le32 rate_n_flags;
|
|
|
|
|
2011-08-26 14:10:44 +08:00
|
|
|
lockdep_assert_held(&priv->shrd->mutex);
|
2011-06-22 21:34:09 +08:00
|
|
|
|
2011-10-10 22:26:54 +08:00
|
|
|
memset(link_cmd, 0, sizeof(*link_cmd));
|
|
|
|
|
2010-09-23 00:02:01 +08:00
|
|
|
/* Set up the rate scaling to start at selected rate, fall back
|
|
|
|
* all the way down to 1M in IEEE order, and then spin on 1M */
|
|
|
|
if (priv->band == IEEE80211_BAND_5GHZ)
|
|
|
|
r = IWL_RATE_6M_INDEX;
|
2011-06-22 21:34:09 +08:00
|
|
|
else if (ctx && ctx->vif && ctx->vif->p2p)
|
|
|
|
r = IWL_RATE_6M_INDEX;
|
2010-09-23 00:02:01 +08:00
|
|
|
else
|
|
|
|
r = IWL_RATE_1M_INDEX;
|
|
|
|
|
|
|
|
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
|
|
|
|
rate_flags |= RATE_MCS_CCK_MSK;
|
|
|
|
|
2011-08-26 14:10:39 +08:00
|
|
|
rate_flags |= first_antenna(hw_params(priv).valid_tx_ant) <<
|
2010-09-23 00:02:01 +08:00
|
|
|
RATE_MCS_ANT_POS;
|
|
|
|
rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
|
|
|
|
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
|
|
|
|
link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
|
|
|
|
|
|
|
|
link_cmd->general_params.single_stream_ant_msk =
|
2011-08-26 14:10:39 +08:00
|
|
|
first_antenna(hw_params(priv).valid_tx_ant);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
link_cmd->general_params.dual_stream_ant_msk =
|
2011-08-26 14:10:39 +08:00
|
|
|
hw_params(priv).valid_tx_ant &
|
|
|
|
~first_antenna(hw_params(priv).valid_tx_ant);
|
2010-09-23 00:02:01 +08:00
|
|
|
if (!link_cmd->general_params.dual_stream_ant_msk) {
|
|
|
|
link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
|
2011-08-26 14:10:39 +08:00
|
|
|
} else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) {
|
2010-09-23 00:02:01 +08:00
|
|
|
link_cmd->general_params.dual_stream_ant_msk =
|
2011-08-26 14:10:39 +08:00
|
|
|
hw_params(priv).valid_tx_ant;
|
2010-09-23 00:02:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
|
|
|
|
link_cmd->agg_params.agg_time_limit =
|
|
|
|
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
|
|
|
|
|
|
|
|
link_cmd->sta_id = sta_id;
|
2011-10-10 22:26:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct iwl_link_quality_cmd *
|
|
|
|
iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
|
|
|
|
{
|
|
|
|
struct iwl_link_quality_cmd *link_cmd;
|
|
|
|
|
|
|
|
link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
|
|
|
|
if (!link_cmd) {
|
|
|
|
IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
iwl_sta_fill_lq(priv, ctx, sta_id, link_cmd);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return link_cmd;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* iwlagn_add_bssid_station - Add the special IBSS BSSID station
|
|
|
|
*
|
|
|
|
* Function sleeps.
|
|
|
|
*/
|
|
|
|
int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
|
|
|
const u8 *addr, u8 *sta_id_r)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
u8 sta_id;
|
|
|
|
struct iwl_link_quality_cmd *link_cmd;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
if (sta_id_r)
|
|
|
|
*sta_id_r = IWL_INVALID_STATION;
|
|
|
|
|
|
|
|
ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
|
|
|
|
if (ret) {
|
|
|
|
IWL_ERR(priv, "Unable to add station %pM\n", addr);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sta_id_r)
|
|
|
|
*sta_id_r = sta_id;
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
priv->stations[sta_id].used |= IWL_STA_LOCAL;
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
/* Set up default rate scaling table in device's station table */
|
2011-06-22 21:34:09 +08:00
|
|
|
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
|
2010-09-23 00:02:01 +08:00
|
|
|
if (!link_cmd) {
|
|
|
|
IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
|
|
|
|
addr);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true);
|
|
|
|
if (ret)
|
|
|
|
IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
priv->stations[sta_id].lq = link_cmd;
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
/*
|
|
|
|
* static WEP keys
|
|
|
|
*
|
|
|
|
* For each context, the device has a table of 4 static WEP keys
|
|
|
|
* (one for each key index) that is updated with the following
|
|
|
|
* commands.
|
|
|
|
*/
|
|
|
|
|
2010-09-23 00:02:01 +08:00
|
|
|
static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
|
|
|
|
struct iwl_rxon_context *ctx,
|
|
|
|
bool send_if_empty)
|
|
|
|
{
|
|
|
|
int i, not_empty = 0;
|
|
|
|
u8 buff[sizeof(struct iwl_wep_cmd) +
|
|
|
|
sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
|
|
|
|
struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
|
|
|
|
size_t cmd_size = sizeof(struct iwl_wep_cmd);
|
|
|
|
struct iwl_host_cmd cmd = {
|
|
|
|
.id = ctx->wep_key_cmd,
|
2011-05-04 22:50:38 +08:00
|
|
|
.data = { wep_cmd, },
|
2010-09-23 00:02:01 +08:00
|
|
|
.flags = CMD_SYNC,
|
|
|
|
};
|
|
|
|
|
|
|
|
might_sleep();
|
|
|
|
|
|
|
|
memset(wep_cmd, 0, cmd_size +
|
|
|
|
(sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
|
|
|
|
|
|
|
|
for (i = 0; i < WEP_KEYS_MAX ; i++) {
|
|
|
|
wep_cmd->key[i].key_index = i;
|
|
|
|
if (ctx->wep_keys[i].key_size) {
|
|
|
|
wep_cmd->key[i].key_offset = i;
|
|
|
|
not_empty = 1;
|
|
|
|
} else {
|
|
|
|
wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
|
|
|
|
}
|
|
|
|
|
|
|
|
wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
|
|
|
|
memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
|
|
|
|
ctx->wep_keys[i].key_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
|
|
|
|
wep_cmd->num_keys = WEP_KEYS_MAX;
|
|
|
|
|
|
|
|
cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
|
|
|
|
|
2011-05-04 22:50:38 +08:00
|
|
|
cmd.len[0] = cmd_size;
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
if (not_empty || send_if_empty)
|
iwlagn: bus layer chooses its transport layer
Remove iwl_transport_register which was a W/A. The bus layer knows what
transport to use. So now, the bus layer gives the upper layer a pointer to the
iwl_trans_ops struct that it wants to use. The upper layer then, allocates the
desired transport layer using iwl_trans_ops->alloc function.
As a result of this, priv->trans, no longer exists, priv holds a pointer to
iwl_shared, which holds a pointer to iwl_trans. This required to change all the
calls to the transport layer from upper layer. While we were at it, trans_X
inlines have been renamed to iwl_trans_X to avoid confusions, which of course
required to rename the functions inside the transport layer because of
conflicts in names. So the static API functions inside the transport layer
implementation have been renamed to iwl_trans_pcie_X.
Until now, the IRQ / Tasklet were initialized in iwl_transport_layer. This is
confusing since the registration doesn't mean to request IRQ, so I added a
handler for that.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-08-26 14:10:48 +08:00
|
|
|
return iwl_trans_send_cmd(trans(priv), &cmd);
|
2010-09-23 00:02:01 +08:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
|
|
|
|
struct iwl_rxon_context *ctx)
|
|
|
|
{
|
2011-08-26 14:10:44 +08:00
|
|
|
lockdep_assert_held(&priv->shrd->mutex);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return iwl_send_static_wepkey_cmd(priv, ctx, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
|
|
|
struct iwl_rxon_context *ctx,
|
|
|
|
struct ieee80211_key_conf *keyconf)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2011-08-26 14:10:44 +08:00
|
|
|
lockdep_assert_held(&priv->shrd->mutex);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
|
|
|
|
keyconf->keyidx);
|
|
|
|
|
|
|
|
memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
|
2011-08-26 14:11:04 +08:00
|
|
|
if (iwl_is_rfkill(priv->shrd)) {
|
2010-09-23 00:02:01 +08:00
|
|
|
IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
|
|
|
|
/* but keys in device are clear anyway so return success */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ret = iwl_send_static_wepkey_cmd(priv, ctx, 1);
|
|
|
|
IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
|
|
|
|
keyconf->keyidx, ret);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int iwl_set_default_wep_key(struct iwl_priv *priv,
|
|
|
|
struct iwl_rxon_context *ctx,
|
|
|
|
struct ieee80211_key_conf *keyconf)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2011-08-26 14:10:44 +08:00
|
|
|
lockdep_assert_held(&priv->shrd->mutex);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
if (keyconf->keylen != WEP_KEY_LEN_128 &&
|
|
|
|
keyconf->keylen != WEP_KEY_LEN_64) {
|
|
|
|
IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
keyconf->hw_key_idx = IWLAGN_HW_KEY_DEFAULT;
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
|
|
|
|
memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
|
|
|
|
keyconf->keylen);
|
|
|
|
|
|
|
|
ret = iwl_send_static_wepkey_cmd(priv, ctx, false);
|
|
|
|
IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
|
|
|
|
keyconf->keylen, keyconf->keyidx, ret);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
/*
|
|
|
|
* dynamic (per-station) keys
|
|
|
|
*
|
|
|
|
* The dynamic keys are a little more complicated. The device has
|
|
|
|
* a key cache of up to STA_KEY_MAX_NUM/STA_KEY_MAX_NUM_PAN keys.
|
|
|
|
* These are linked to stations by a table that contains an index
|
|
|
|
* into the key table for each station/key index/{mcast,unicast},
|
|
|
|
* i.e. it's basically an array of pointers like this:
|
|
|
|
* key_offset_t key_mapping[NUM_STATIONS][4][2];
|
|
|
|
* (it really works differently, but you can think of it as such)
|
|
|
|
*
|
|
|
|
* The key uploading and linking happens in the same command, the
|
|
|
|
* add station command with STA_MODIFY_KEY_MASK.
|
|
|
|
*/
|
2010-09-23 00:02:01 +08:00
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
static u8 iwlagn_key_sta_id(struct iwl_priv *priv,
|
|
|
|
struct ieee80211_vif *vif,
|
|
|
|
struct ieee80211_sta *sta)
|
|
|
|
{
|
|
|
|
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
|
|
|
u8 sta_id = IWL_INVALID_STATION;
|
|
|
|
|
|
|
|
if (sta)
|
|
|
|
sta_id = iwl_sta_id(sta);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The device expects GTKs for station interfaces to be
|
|
|
|
* installed as GTKs for the AP station. If we have no
|
|
|
|
* station ID, then use the ap_sta_id in that case.
|
|
|
|
*/
|
|
|
|
if (!sta && vif && vif_priv->ctx) {
|
|
|
|
switch (vif->type) {
|
|
|
|
case NL80211_IFTYPE_STATION:
|
|
|
|
sta_id = vif_priv->ctx->ap_sta_id;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* In all other cases, the key will be
|
|
|
|
* used either for TX only or is bound
|
|
|
|
* to a station already.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-09-23 00:02:01 +08:00
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
return sta_id;
|
2010-09-23 00:02:01 +08:00
|
|
|
}
|
|
|
|
|
2011-07-17 16:44:11 +08:00
|
|
|
static int iwlagn_send_sta_key(struct iwl_priv *priv,
|
|
|
|
struct ieee80211_key_conf *keyconf,
|
|
|
|
u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
|
|
|
|
u32 cmd_flags)
|
2010-09-23 00:02:01 +08:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
__le16 key_flags;
|
2010-09-23 00:02:01 +08:00
|
|
|
struct iwl_addsta_cmd sta_cmd;
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
int i;
|
2011-07-17 16:44:11 +08:00
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
|
|
|
key_flags |= STA_KEY_FLG_MAP_KEY_MSK;
|
2010-09-23 00:02:01 +08:00
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
switch (keyconf->cipher) {
|
|
|
|
case WLAN_CIPHER_SUITE_CCMP:
|
|
|
|
key_flags |= STA_KEY_FLG_CCMP;
|
|
|
|
memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
|
|
|
|
break;
|
|
|
|
case WLAN_CIPHER_SUITE_TKIP:
|
|
|
|
key_flags |= STA_KEY_FLG_TKIP;
|
|
|
|
sta_cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
|
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
sta_cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
|
|
|
|
memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
|
|
|
|
break;
|
|
|
|
case WLAN_CIPHER_SUITE_WEP104:
|
|
|
|
key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
|
|
|
|
/* fall through */
|
|
|
|
case WLAN_CIPHER_SUITE_WEP40:
|
|
|
|
key_flags |= STA_KEY_FLG_WEP;
|
|
|
|
memcpy(&sta_cmd.key.key[3], keyconf->key, keyconf->keylen);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WARN_ON(1);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2010-09-23 00:02:01 +08:00
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
2010-09-23 00:02:01 +08:00
|
|
|
key_flags |= STA_KEY_MULTICAST_MSK;
|
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
/* key pointer (offset) */
|
|
|
|
sta_cmd.key.key_offset = keyconf->hw_key_idx;
|
2010-09-23 00:02:01 +08:00
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
sta_cmd.key.key_flags = key_flags;
|
|
|
|
sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
|
|
|
|
sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
2010-09-23 00:02:01 +08:00
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
return iwl_send_add_sta(priv, &sta_cmd, cmd_flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void iwl_update_tkip_key(struct iwl_priv *priv,
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
struct ieee80211_vif *vif,
|
2010-09-23 00:02:01 +08:00
|
|
|
struct ieee80211_key_conf *keyconf,
|
|
|
|
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
|
|
|
|
{
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
u8 sta_id = iwlagn_key_sta_id(priv, vif, sta);
|
|
|
|
|
|
|
|
if (sta_id == IWL_INVALID_STATION)
|
|
|
|
return;
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
if (iwl_scan_cancel(priv)) {
|
|
|
|
/* cancel scan failed, just live w/ bad key and rely
|
|
|
|
briefly on SW decryption */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-07-17 16:44:11 +08:00
|
|
|
iwlagn_send_sta_key(priv, keyconf, sta_id,
|
|
|
|
iv32, phase1key, CMD_ASYNC);
|
2010-09-23 00:02:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
|
|
|
struct iwl_rxon_context *ctx,
|
|
|
|
struct ieee80211_key_conf *keyconf,
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
struct ieee80211_sta *sta)
|
2010-09-23 00:02:01 +08:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
struct iwl_addsta_cmd sta_cmd;
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
|
|
|
|
|
|
|
|
/* if station isn't there, neither is the key */
|
|
|
|
if (sta_id == IWL_INVALID_STATION)
|
|
|
|
return -ENOENT;
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
|
|
|
|
if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE))
|
|
|
|
sta_id = IWL_INVALID_STATION;
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
|
|
|
|
if (sta_id == IWL_INVALID_STATION)
|
|
|
|
return 0;
|
2010-09-23 00:02:01 +08:00
|
|
|
|
2011-08-26 14:10:44 +08:00
|
|
|
lockdep_assert_held(&priv->shrd->mutex);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
ctx->key_mapping_keys--;
|
|
|
|
|
|
|
|
IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
|
|
|
|
keyconf->keyidx, sta_id);
|
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
if (!test_and_clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table))
|
|
|
|
IWL_ERR(priv, "offset %d not used in uCode key table.\n",
|
|
|
|
keyconf->hw_key_idx);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
sta_cmd.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
|
|
|
|
sta_cmd.key.key_offset = WEP_INVALID_OFFSET;
|
|
|
|
sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
|
|
|
sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
|
|
|
}
|
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
int iwl_set_dynamic_key(struct iwl_priv *priv,
|
|
|
|
struct iwl_rxon_context *ctx,
|
|
|
|
struct ieee80211_key_conf *keyconf,
|
|
|
|
struct ieee80211_sta *sta)
|
2010-09-23 00:02:01 +08:00
|
|
|
{
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
struct ieee80211_key_seq seq;
|
|
|
|
u16 p1k[5];
|
2010-09-23 00:02:01 +08:00
|
|
|
int ret;
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
|
|
|
|
const u8 *addr;
|
|
|
|
|
|
|
|
if (sta_id == IWL_INVALID_STATION)
|
|
|
|
return -EINVAL;
|
2010-09-23 00:02:01 +08:00
|
|
|
|
2011-08-26 14:10:44 +08:00
|
|
|
lockdep_assert_held(&priv->shrd->mutex);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
|
|
|
|
if (keyconf->hw_key_idx == WEP_INVALID_OFFSET)
|
|
|
|
return -ENOSPC;
|
|
|
|
|
2010-09-23 00:02:01 +08:00
|
|
|
ctx->key_mapping_keys++;
|
|
|
|
|
|
|
|
switch (keyconf->cipher) {
|
|
|
|
case WLAN_CIPHER_SUITE_TKIP:
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
|
|
|
|
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
|
|
|
|
|
|
|
if (sta)
|
|
|
|
addr = sta->addr;
|
|
|
|
else /* station mode case only */
|
|
|
|
addr = ctx->active.bssid_addr;
|
|
|
|
|
|
|
|
/* pre-fill phase 1 key into device cache */
|
|
|
|
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
|
|
|
|
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
|
2011-07-17 16:44:11 +08:00
|
|
|
ret = iwlagn_send_sta_key(priv, keyconf, sta_id,
|
|
|
|
seq.tkip.iv32, p1k, CMD_SYNC);
|
2010-09-23 00:02:01 +08:00
|
|
|
break;
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
case WLAN_CIPHER_SUITE_CCMP:
|
|
|
|
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
|
|
|
/* fall through */
|
2010-09-23 00:02:01 +08:00
|
|
|
case WLAN_CIPHER_SUITE_WEP40:
|
|
|
|
case WLAN_CIPHER_SUITE_WEP104:
|
2011-07-17 16:44:11 +08:00
|
|
|
ret = iwlagn_send_sta_key(priv, keyconf, sta_id,
|
|
|
|
0, NULL, CMD_SYNC);
|
2010-09-23 00:02:01 +08:00
|
|
|
break;
|
|
|
|
default:
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
IWL_ERR(priv, "Unknown cipher %x\n", keyconf->cipher);
|
2010-09-23 00:02:01 +08:00
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
|
|
|
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
if (ret) {
|
|
|
|
ctx->key_mapping_keys--;
|
|
|
|
clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table);
|
|
|
|
}
|
|
|
|
|
|
|
|
IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n",
|
2010-09-23 00:02:01 +08:00
|
|
|
keyconf->cipher, keyconf->keylen, keyconf->keyidx,
|
iwlagn: rewrite HW crypto
As I just discovered while doing WoWLAN, HW crypto
is done wrong for GTKs: they should be programmed
for the AP station ID (in the managed mode case)
and the HW can actually deal with multiple group
keys per station as well (which is useful in IBSS
RSN but that I've chosen not to use this).
To fix all this, modify the way keys are sent to
the device and key offsets are allocated. After
these changes, key offsets are stored into the
hw_key_idx which we can then track for the key
lifetime, not relying on our sta_cmd array. WEP
default keys get special treatment, of course.
Additionally, since I had the API for it, we can
now pre-fill TKIP phase 1 keys for RX now that we
can obtain the P1K from mac80211, a capability I
had added for WoWLAN initially.
Finally, some keys simply don't need to be added
into the device's key cache -- a key that won't
be used for RX is only needed in the TX header,
so "pretend" to have accepted any key without
adding it into the device -- no need to use up
key space there for it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
2011-07-16 04:03:12 +08:00
|
|
|
sta ? sta->addr : NULL, ret);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* iwlagn_alloc_bcast_station - add broadcast station into driver's station table.
|
|
|
|
*
|
|
|
|
* This adds the broadcast station into the driver's station table
|
|
|
|
* and marks it driver active, so that it will be restored to the
|
|
|
|
* device at the next best time.
|
|
|
|
*/
|
|
|
|
int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
|
|
|
|
struct iwl_rxon_context *ctx)
|
|
|
|
{
|
|
|
|
struct iwl_link_quality_cmd *link_cmd;
|
|
|
|
unsigned long flags;
|
|
|
|
u8 sta_id;
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
|
|
|
|
if (sta_id == IWL_INVALID_STATION) {
|
|
|
|
IWL_ERR(priv, "Unable to prepare broadcast station\n");
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
|
|
|
|
priv->stations[sta_id].used |= IWL_STA_BCAST;
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
2011-06-22 21:34:09 +08:00
|
|
|
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
|
2010-09-23 00:02:01 +08:00
|
|
|
if (!link_cmd) {
|
|
|
|
IWL_ERR(priv,
|
|
|
|
"Unable to initialize rate scaling for bcast station.\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
priv->stations[sta_id].lq = link_cmd;
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* iwl_update_bcast_station - update broadcast station's LQ command
|
|
|
|
*
|
|
|
|
* Only used by iwlagn. Placed here to have all bcast station management
|
|
|
|
* code together.
|
|
|
|
*/
|
2011-06-22 21:34:09 +08:00
|
|
|
int iwl_update_bcast_station(struct iwl_priv *priv,
|
|
|
|
struct iwl_rxon_context *ctx)
|
2010-09-23 00:02:01 +08:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
struct iwl_link_quality_cmd *link_cmd;
|
|
|
|
u8 sta_id = ctx->bcast_sta_id;
|
|
|
|
|
2011-06-22 21:34:09 +08:00
|
|
|
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
|
2010-09-23 00:02:01 +08:00
|
|
|
if (!link_cmd) {
|
|
|
|
IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
if (priv->stations[sta_id].lq)
|
|
|
|
kfree(priv->stations[sta_id].lq);
|
|
|
|
else
|
|
|
|
IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
|
|
|
|
priv->stations[sta_id].lq = link_cmd;
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int iwl_update_bcast_stations(struct iwl_priv *priv)
|
|
|
|
{
|
|
|
|
struct iwl_rxon_context *ctx;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
for_each_context(priv, ctx) {
|
|
|
|
ret = iwl_update_bcast_station(priv, ctx);
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
|
|
|
|
*/
|
|
|
|
int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
struct iwl_addsta_cmd sta_cmd;
|
|
|
|
|
2011-08-26 14:10:44 +08:00
|
|
|
lockdep_assert_held(&priv->shrd->mutex);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
/* Remove "disable" flag, to enable Tx for this TID */
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
|
|
|
|
priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
|
|
|
|
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
|
|
|
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
|
|
|
}
|
|
|
|
|
|
|
|
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
|
|
|
int tid, u16 ssn)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
int sta_id;
|
|
|
|
struct iwl_addsta_cmd sta_cmd;
|
|
|
|
|
2011-08-26 14:10:44 +08:00
|
|
|
lockdep_assert_held(&priv->shrd->mutex);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
sta_id = iwl_sta_id(sta);
|
|
|
|
if (sta_id == IWL_INVALID_STATION)
|
|
|
|
return -ENXIO;
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
priv->stations[sta_id].sta.station_flags_msk = 0;
|
|
|
|
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
|
|
|
|
priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
|
|
|
|
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
|
|
|
|
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
|
|
|
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
|
|
|
}
|
|
|
|
|
|
|
|
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
|
|
|
int tid)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
int sta_id;
|
|
|
|
struct iwl_addsta_cmd sta_cmd;
|
|
|
|
|
2011-08-26 14:10:44 +08:00
|
|
|
lockdep_assert_held(&priv->shrd->mutex);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
sta_id = iwl_sta_id(sta);
|
|
|
|
if (sta_id == IWL_INVALID_STATION) {
|
|
|
|
IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
|
|
|
|
return -ENXIO;
|
|
|
|
}
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
priv->stations[sta_id].sta.station_flags_msk = 0;
|
|
|
|
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
|
|
|
|
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
|
|
|
|
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
|
|
|
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
|
|
|
}
|
|
|
|
|
2010-11-11 01:56:38 +08:00
|
|
|
static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
2010-09-23 00:02:01 +08:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
|
|
|
|
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
|
|
|
priv->stations[sta_id].sta.sta.modify_mask = 0;
|
|
|
|
priv->stations[sta_id].sta.sleep_tx_count = 0;
|
|
|
|
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
|
|
|
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
|
|
|
|
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
|
|
|
priv->stations[sta_id].sta.sta.modify_mask =
|
|
|
|
STA_MODIFY_SLEEP_TX_COUNT_MSK;
|
|
|
|
priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
|
|
|
|
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
|
|
|
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
2011-08-26 14:10:47 +08:00
|
|
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
2010-09-23 00:02:01 +08:00
|
|
|
|
|
|
|
}
|
2010-11-11 01:56:38 +08:00
|
|
|
|
|
|
|
void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
|
|
|
|
struct ieee80211_vif *vif,
|
|
|
|
enum sta_notify_cmd cmd,
|
|
|
|
struct ieee80211_sta *sta)
|
|
|
|
{
|
|
|
|
struct iwl_priv *priv = hw->priv;
|
|
|
|
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
|
|
|
int sta_id;
|
|
|
|
|
2011-10-10 22:27:10 +08:00
|
|
|
IWL_DEBUG_MAC80211(priv, "enter\n");
|
|
|
|
|
2010-11-11 01:56:38 +08:00
|
|
|
switch (cmd) {
|
|
|
|
case STA_NOTIFY_SLEEP:
|
|
|
|
WARN_ON(!sta_priv->client);
|
|
|
|
sta_priv->asleep = true;
|
|
|
|
if (atomic_read(&sta_priv->pending_frames) > 0)
|
|
|
|
ieee80211_sta_block_awake(hw, sta, true);
|
|
|
|
break;
|
|
|
|
case STA_NOTIFY_AWAKE:
|
|
|
|
WARN_ON(!sta_priv->client);
|
|
|
|
if (!sta_priv->asleep)
|
|
|
|
break;
|
|
|
|
sta_priv->asleep = false;
|
|
|
|
sta_id = iwl_sta_id(sta);
|
|
|
|
if (sta_id != IWL_INVALID_STATION)
|
|
|
|
iwl_sta_modify_ps_wake(priv, sta_id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2011-10-10 22:27:10 +08:00
|
|
|
IWL_DEBUG_MAC80211(priv, "leave\n");
|
2010-11-11 01:56:38 +08:00
|
|
|
}
|