summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c163
1 files changed, 93 insertions, 70 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index c7e1d7d09e02..935e64311d39 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -509,11 +509,11 @@ 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 */
- if (info->flags & IEEE80211_TX_CTL_INJECTED)
+ /* Find index into station table for destination station */
+ if (!info->control.sta)
sta_id = priv->hw_params.bcast_sta_id;
else
- sta_id = iwl_get_sta_id(priv, hdr);
+ sta_id = iwl_sta_id(info->control.sta);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1);
@@ -1848,7 +1848,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 n_probes,
- struct iwl3945_scan_channel *scan_ch)
+ struct iwl3945_scan_channel *scan_ch,
+ struct ieee80211_vif *vif)
{
struct ieee80211_channel *chan;
const struct ieee80211_supported_band *sband;
@@ -1862,7 +1863,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
return 0;
active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
- passive_dwell = iwl_get_passive_dwell_time(priv, band);
+ passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
@@ -2110,6 +2111,28 @@ static void iwl3945_nic_start(struct iwl_priv *priv)
iwl_write32(priv, CSR_RESET, 0);
}
+#define IWL3945_UCODE_GET(item) \
+static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\
+{ \
+ return le32_to_cpu(ucode->u.v1.item); \
+}
+
+static u32 iwl3945_ucode_get_header_size(u32 api_ver)
+{
+ return 24;
+}
+
+static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode)
+{
+ return (u8 *) ucode->u.v1.data;
+}
+
+IWL3945_UCODE_GET(inst_size);
+IWL3945_UCODE_GET(data_size);
+IWL3945_UCODE_GET(init_size);
+IWL3945_UCODE_GET(init_data_size);
+IWL3945_UCODE_GET(boot_size);
+
/**
* iwl3945_read_ucode - Read uCode images from disk file.
*
@@ -2158,7 +2181,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
goto error;
/* Make sure that we got at least our header! */
- if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
+ if (ucode_raw->size < iwl3945_ucode_get_header_size(1)) {
IWL_ERR(priv, "File size way too small!\n");
ret = -EINVAL;
goto err_release;
@@ -2169,13 +2192,12 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
priv->ucode_ver = le32_to_cpu(ucode->ver);
api_ver = IWL_UCODE_API(priv->ucode_ver);
- inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
- data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
- init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
- init_data_size =
- priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
- boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
- src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
+ inst_size = iwl3945_ucode_get_inst_size(ucode);
+ data_size = iwl3945_ucode_get_data_size(ucode);
+ init_size = iwl3945_ucode_get_init_size(ucode);
+ init_data_size = iwl3945_ucode_get_init_data_size(ucode);
+ boot_size = iwl3945_ucode_get_boot_size(ucode);
+ src = iwl3945_ucode_get_data(ucode);
/* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
@@ -2224,7 +2246,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
/* Verify size of file vs. image size info in file's header */
- if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) +
+ if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) +
inst_size + data_size + init_size +
init_data_size + boot_size) {
@@ -2523,7 +2545,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
/* Initialize our rx_config data */
- iwl_connection_init_rx_config(priv, priv->iw_mode);
+ iwl_connection_init_rx_config(priv, NULL);
}
/* Configure Bluetooth device coexistence support */
@@ -2562,7 +2584,9 @@ static void __iwl3945_down(struct iwl_priv *priv)
set_bit(STATUS_EXIT_PENDING, &priv->status);
/* Station information will now be cleared in device */
- iwl_clear_ucode_stations(priv, true);
+ iwl_clear_ucode_stations(priv);
+ iwl_dealloc_bcast_station(priv);
+ iwl_clear_driver_stations(priv);
/* Unblock any waiting calls */
wake_up_interruptible_all(&priv->wait_command_queue);
@@ -2643,6 +2667,10 @@ static int __iwl3945_up(struct iwl_priv *priv)
{
int rc, i;
+ rc = iwl_alloc_bcast_station(priv, false);
+ if (rc)
+ return rc;
+
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
return -EIO;
@@ -2791,7 +2819,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
}
-void iwl3945_request_scan(struct iwl_priv *priv)
+void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
@@ -2872,7 +2900,7 @@ void iwl3945_request_scan(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
spin_lock_irqsave(&priv->lock, flags);
- interval = priv->beacon_int;
+ interval = vif ? vif->bss_conf.beacon_int : 0;
spin_unlock_irqrestore(&priv->lock, flags);
scan->suspend_time = 0;
@@ -2967,7 +2995,7 @@ void iwl3945_request_scan(struct iwl_priv *priv)
scan->channel_count =
iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
@@ -3040,26 +3068,25 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
mutex_unlock(&priv->mutex);
}
-void iwl3945_post_associate(struct iwl_priv *priv)
+void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
int rc = 0;
struct ieee80211_conf *conf = NULL;
- if (priv->iw_mode == NL80211_IFTYPE_AP) {
+ if (!vif || !priv->is_open)
+ return;
+
+ if (vif->type == NL80211_IFTYPE_AP) {
IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
return;
}
-
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
- priv->assoc_id, priv->active_rxon.bssid_addr);
+ vif->bss_conf.aid, priv->active_rxon.bssid_addr);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (!priv->vif || !priv->is_open)
- return;
-
iwl_scan_cancel_timeout(priv, 200);
conf = ieee80211_get_hw_conf(priv->hw);
@@ -3068,7 +3095,7 @@ void iwl3945_post_associate(struct iwl_priv *priv)
iwlcore_commit_rxon(priv);
memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv);
+ iwl_setup_rxon_timing(priv, vif);
rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing), &priv->rxon_timing);
if (rc)
@@ -3077,51 +3104,38 @@ void iwl3945_post_associate(struct iwl_priv *priv)
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
- priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
+ priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
- priv->assoc_id, priv->beacon_int);
+ vif->bss_conf.aid, vif->bss_conf.beacon_int);
- if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+ if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
- if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+ if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
- if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
+ if (vif->type == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-
}
iwlcore_commit_rxon(priv);
- switch (priv->iw_mode) {
+ switch (vif->type) {
case NL80211_IFTYPE_STATION:
iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
break;
-
case NL80211_IFTYPE_ADHOC:
-
- priv->assoc_id = 1;
- iwl_add_local_station(priv, priv->bssid, false);
- iwl3945_sync_sta(priv, IWL_STA_ID,
- (priv->band == IEEE80211_BAND_5GHZ) ?
- IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
- CMD_ASYNC);
- iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
-
iwl3945_send_beacon_cmd(priv);
-
break;
-
default:
- IWL_ERR(priv, "%s Should not be called in %d mode\n",
- __func__, priv->iw_mode);
+ IWL_ERR(priv, "%s Should not be called in %d mode\n",
+ __func__, vif->type);
break;
}
}
@@ -3245,7 +3259,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return NETDEV_TX_OK;
}
-void iwl3945_config_ap(struct iwl_priv *priv)
+void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
int rc = 0;
@@ -3261,7 +3275,7 @@ void iwl3945_config_ap(struct iwl_priv *priv)
/* RXON Timing */
memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv);
+ iwl_setup_rxon_timing(priv, vif);
rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing),
&priv->rxon_timing);
@@ -3269,9 +3283,10 @@ void iwl3945_config_ap(struct iwl_priv *priv)
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
"Attempting to continue.\n");
- /* FIXME: what should be the assoc_id for AP? */
- priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
- if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+ priv->staging_rxon.assoc_id = 0;
+
+ if (vif->bss_conf.assoc_capability &
+ WLAN_CAPABILITY_SHORT_PREAMBLE)
priv->staging_rxon.flags |=
RXON_FLG_SHORT_PREAMBLE_MSK;
else
@@ -3279,22 +3294,21 @@ void iwl3945_config_ap(struct iwl_priv *priv)
~RXON_FLG_SHORT_PREAMBLE_MSK;
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
- if (priv->assoc_capability &
- WLAN_CAPABILITY_SHORT_SLOT_TIME)
+ if (vif->bss_conf.assoc_capability &
+ WLAN_CAPABILITY_SHORT_SLOT_TIME)
priv->staging_rxon.flags |=
RXON_FLG_SHORT_SLOT_MSK;
else
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
- if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
+ if (vif->type == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
}
/* restore RXON assoc */
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
iwlcore_commit_rxon(priv);
- iwl_add_local_station(priv, iwl_bcast_addr, false);
}
iwl3945_send_beacon_cmd(priv);
@@ -3309,7 +3323,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_key_conf *key)
{
struct iwl_priv *priv = hw->priv;
- const u8 *addr;
int ret = 0;
u8 sta_id = IWL_INVALID_STATION;
u8 static_key;
@@ -3321,15 +3334,19 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return -EOPNOTSUPP;
}
- addr = sta ? sta->addr : iwl_bcast_addr;
static_key = !iwl_is_associated(priv);
if (!static_key) {
- sta_id = iwl_find_station(priv, addr);
- if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
- addr);
- return -EINVAL;
+ if (!sta) {
+ sta_id = priv->hw_params.bcast_sta_id;
+ } else {
+ sta_id = iwl_sta_id(sta);
+ if (sta_id == IWL_INVALID_STATION) {
+ IWL_DEBUG_MAC80211(priv,
+ "leave - %pM not in station map.\n",
+ sta->addr);
+ return -EINVAL;
+ }
}
}
@@ -3366,10 +3383,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
struct ieee80211_sta *sta)
{
struct iwl_priv *priv = hw->priv;
+ struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
int ret;
- bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION;
+ bool is_ap = vif->type == NL80211_IFTYPE_STATION;
u8 sta_id;
+ sta_priv->common.sta_id = IWL_INVALID_STATION;
+
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
sta->addr);
@@ -3382,16 +3402,14 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
return ret;
}
+ sta_priv->common.sta_id = sta_id;
+
/* Initialize rate scaling */
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl3945_rs_rate_init(priv, sta, sta_id);
return 0;
-
-
-
- return ret;
}
/*****************************************************************************
*
@@ -3740,6 +3758,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
+ INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
iwl3945_hw_setup_deferred_work(priv);
@@ -3762,6 +3781,7 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
+ cancel_work_sync(&priv->start_internal_scan);
cancel_work_sync(&priv->beacon_update);
if (priv->cfg->ops->lib->recover_from_tx_stall)
del_timer_sync(&priv->monitor_recover);
@@ -3864,6 +3884,8 @@ err:
return ret;
}
+#define IWL3945_MAX_PROBE_REQUEST 200
+
static int iwl3945_setup_mac(struct iwl_priv *priv)
{
int ret;
@@ -3871,6 +3893,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
hw->rate_control_algorithm = "iwl-3945-rs";
hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+ hw->vif_data_size = sizeof(struct iwl_vif_priv);
/* Tell mac80211 our characteristics */
hw->flags = IEEE80211_HW_SIGNAL_DBM |
@@ -3889,7 +3912,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
/* we create the 802.11 header and a zero-length SSID element */
- hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
+ hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2;
/* Default value; 4 EDCA QOS priorities */
hw->queues = 4;