summaryrefslogtreecommitdiffstats
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.c640
1 files changed, 311 insertions, 329 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index a27872de4106..8f8c4b73f8b9 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -27,10 +27,13 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/pci-aspm.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
@@ -141,7 +144,7 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- if (sta_id == priv->hw_params.bcast_sta_id)
+ if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
key_flags |= STA_KEY_MULTICAST_MSK;
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
@@ -149,7 +152,7 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
key_flags &= ~STA_KEY_FLG_INVALID;
spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].keyinfo.alg = keyconf->alg;
+ priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
keyconf->keylen);
@@ -197,6 +200,7 @@ static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
{
unsigned long flags;
+ struct iwl_addsta_cmd sta_cmd;
spin_lock_irqsave(&priv->sta_lock, flags);
memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
@@ -205,11 +209,11 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags);
IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
- iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0);
- return 0;
+ return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
}
static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
@@ -219,23 +223,25 @@ static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
keyconf->hw_key_idx = HW_KEY_DYNAMIC;
- switch (keyconf->alg) {
- case ALG_CCMP:
+ switch (keyconf->cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
break;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
break;
- case ALG_WEP:
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
break;
default:
- IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
+ IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__,
+ keyconf->cipher);
ret = -EINVAL;
}
- IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n",
- keyconf->alg, keyconf->keylen, keyconf->keyidx,
+ IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
+ keyconf->cipher, keyconf->keylen, keyconf->keyidx,
sta_id, ret);
return ret;
@@ -251,10 +257,11 @@ static int iwl3945_remove_static_key(struct iwl_priv *priv)
static int iwl3945_set_static_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key)
{
- if (key->alg == ALG_WEP)
+ if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ key->cipher == WLAN_CIPHER_SUITE_WEP104)
return -EOPNOTSUPP;
- IWL_ERR(priv, "Static key invalid: alg %d\n", key->alg);
+ IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher);
return -EINVAL;
}
@@ -310,17 +317,15 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
int left)
{
- if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
- ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
- (priv->iw_mode != NL80211_IFTYPE_AP)))
+ if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
return 0;
- if (priv->ibss_beacon->len > left)
+ if (priv->beacon_skb->len > left)
return 0;
- memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
+ memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
- return priv->ibss_beacon->len;
+ return priv->beacon_skb->len;
}
static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
@@ -338,7 +343,8 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
return -ENOMEM;
}
- rate = iwl_rate_get_lowest_plcp(priv);
+ rate = iwl_rate_get_lowest_plcp(priv,
+ &priv->contexts[IWL_RXON_CTX_BSS]);
frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
@@ -368,23 +374,25 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
- switch (keyinfo->alg) {
- case ALG_CCMP:
+ tx_cmd->sec_ctl = 0;
+
+ switch (keyinfo->cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
break;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
break;
- case ALG_WEP:
- tx_cmd->sec_ctl = TX_CMD_SEC_WEP |
+ case WLAN_CIPHER_SUITE_WEP104:
+ tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+ /* fall through */
+ case WLAN_CIPHER_SUITE_WEP40:
+ tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
(info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
- if (keyinfo->keylen == 13)
- tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-
memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
@@ -392,7 +400,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
break;
default:
- IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg);
+ IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher);
break;
}
}
@@ -434,10 +442,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
}
- priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags);
-
- if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
- tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+ priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
if (ieee80211_is_mgmt(fc)) {
@@ -474,10 +479,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
u8 unicast;
u8 sta_id;
u8 tid = 0;
- u16 seq_number = 0;
__le16 fc;
u8 wait_write_ptr = 0;
- u8 *qc = NULL;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
@@ -510,10 +513,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr_len = ieee80211_hdrlen(fc);
/* Find index into station table for destination station */
- if (!info->control.sta)
- sta_id = priv->hw_params.bcast_sta_id;
- else
- sta_id = iwl_sta_id(info->control.sta);
+ sta_id = iwl_sta_id_or_broadcast(
+ priv, &priv->contexts[IWL_RXON_CTX_BSS],
+ info->control.sta);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1);
@@ -523,16 +525,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
if (ieee80211_is_data_qos(fc)) {
- qc = ieee80211_get_qos_ctl(hdr);
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
if (unlikely(tid >= MAX_TID_COUNT))
goto drop;
- seq_number = priv->stations[sta_id].tid[tid].seq_number &
- IEEE80211_SCTL_SEQ;
- hdr->seq_ctrl = cpu_to_le16(seq_number) |
- (hdr->seq_ctrl &
- cpu_to_le16(IEEE80211_SCTL_FRAG));
- seq_number += 0x10;
}
/* Descriptor for chosen Tx queue */
@@ -548,7 +544,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Set up driver data for this TFD */
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
- txq->txb[q->write_ptr].skb[0] = skb;
+ txq->txb[q->write_ptr].skb = skb;
+ txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS];
/* Init first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq->cmd[idx];
@@ -591,8 +588,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (!ieee80211_has_morefrags(hdr->frame_control)) {
txq->need_update = 1;
- if (qc)
- priv->stations[sta_id].tid[tid].seq_number = seq_number;
} else {
wait_write_ptr = 1;
txq->need_update = 0;
@@ -631,8 +626,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
len, PCI_DMA_TODEVICE);
/* we do not map meta data ... so we can safely access address to
* provide to unmap command*/
- pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
- pci_unmap_len_set(out_meta, len, len);
+ dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+ dma_unmap_len_set(out_meta, len, len);
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
@@ -677,55 +672,6 @@ drop:
return -1;
}
-#define BEACON_TIME_MASK_LOW 0x00FFFFFF
-#define BEACON_TIME_MASK_HIGH 0xFF000000
-#define TIME_UNIT 1024
-
-/*
- * extended beacon time format
- * time in usec will be changed into a 32-bit value in 8:24 format
- * the high 1 byte is the beacon counts
- * the lower 3 bytes is the time in usec within one beacon interval
- */
-
-static u32 iwl3945_usecs_to_beacons(u32 usec, u32 beacon_interval)
-{
- u32 quot;
- u32 rem;
- u32 interval = beacon_interval * 1024;
-
- if (!interval || !usec)
- return 0;
-
- quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
- rem = (usec % interval) & BEACON_TIME_MASK_LOW;
-
- return (quot << 24) + rem;
-}
-
-/* base is usually what we get from ucode with each received frame,
- * the same as HW timer counter counting down
- */
-
-static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
-{
- u32 base_low = base & BEACON_TIME_MASK_LOW;
- u32 addon_low = addon & BEACON_TIME_MASK_LOW;
- u32 interval = beacon_interval * TIME_UNIT;
- u32 res = (base & BEACON_TIME_MASK_HIGH) +
- (addon & BEACON_TIME_MASK_HIGH);
-
- if (base_low > addon_low)
- res += base_low - addon_low;
- else if (base_low < addon_low) {
- res += interval + base_low - addon_low;
- res += (1 << 24);
- } else
- res += (1 << 24);
-
- return cpu_to_le32(res);
-}
-
static int iwl3945_get_measurement(struct iwl_priv *priv,
struct ieee80211_measurement_params *params,
u8 type)
@@ -741,12 +687,12 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
int rc;
int spectrum_resp_status;
int duration = le16_to_cpu(params->duration);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- if (iwl_is_associated(priv))
- add_time =
- iwl3945_usecs_to_beacons(
+ if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
+ add_time = iwl_usecs_to_beacons(priv,
le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
- le16_to_cpu(priv->rxon_timing.beacon_interval));
+ le16_to_cpu(ctx->timing.beacon_interval));
memset(&spectrum, 0, sizeof(spectrum));
@@ -757,18 +703,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
cmd.len = sizeof(spectrum);
spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
- if (iwl_is_associated(priv))
+ if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
spectrum.start_time =
- iwl3945_add_beacon_time(priv->_3945.last_beacon_time,
- add_time,
- le16_to_cpu(priv->rxon_timing.beacon_interval));
+ iwl_add_beacon_time(priv,
+ priv->_3945.last_beacon_time, add_time,
+ le16_to_cpu(ctx->timing.beacon_interval));
else
spectrum.start_time = 0;
spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
spectrum.channels[0].channel = params->channel;
spectrum.channels[0].type = type;
- if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
+ if (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
spectrum.flags |= RXON_FLG_BAND_24G_MSK |
RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
@@ -857,7 +803,8 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
struct sk_buff *beacon;
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
- beacon = ieee80211_beacon_get(priv->hw, priv->vif);
+ beacon = ieee80211_beacon_get(priv->hw,
+ priv->contexts[IWL_RXON_CTX_BSS].vif);
if (!beacon) {
IWL_ERR(priv, "update beacon failed\n");
@@ -866,10 +813,10 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
mutex_lock(&priv->mutex);
/* new beacon skb is allocated every time; dispose previous.*/
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
+ if (priv->beacon_skb)
+ dev_kfree_skb(priv->beacon_skb);
- priv->ibss_beacon = beacon;
+ priv->beacon_skb = beacon;
mutex_unlock(&priv->mutex);
iwl3945_send_beacon_cmd(priv);
@@ -878,9 +825,9 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
+#ifdef CONFIG_IWLWIFI_DEBUG
u8 rate = beacon->beacon_notify_hdr.rate;
IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
@@ -892,6 +839,8 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(beacon->low_tsf), rate);
#endif
+ priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!test_bit(STATUS_EXIT_PENDING, &priv->status)))
queue_work(priv->workqueue, &priv->beacon_update);
@@ -1233,7 +1182,7 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
}
dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->dma_addr);
+ rxq->bd_dma);
dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL;
@@ -1314,6 +1263,8 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
while (i != r) {
+ int len;
+
rxb = rxq->queue[i];
/* If an RXB doesn't have a Rx queue slot associated with it,
@@ -1328,8 +1279,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
PCI_DMA_FROMDEVICE);
pkt = rxb_addr(rxb);
- trace_iwlwifi_dev_rx(priv, pkt,
- le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
+ len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+ len += sizeof(u32); /* account for status word */
+ trace_iwlwifi_dev_rx(priv, pkt, len);
/* Reclaim a command buffer only if this packet is a response
* to a (driver-originated) command.
@@ -1483,7 +1435,7 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32));
IWL_ERR(priv,
- "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
+ "%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
desc_lookup(desc), desc, time, blink1, blink2,
ilink1, ilink2, data1);
trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0,
@@ -1629,16 +1581,16 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
- if (capacity > priv->cfg->max_event_log_size) {
+ if (capacity > priv->cfg->base_params->max_event_log_size) {
IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
- capacity, priv->cfg->max_event_log_size);
- capacity = priv->cfg->max_event_log_size;
+ capacity, priv->cfg->base_params->max_event_log_size);
+ capacity = priv->cfg->base_params->max_event_log_size;
}
- if (next_entry > priv->cfg->max_event_log_size) {
+ if (next_entry > priv->cfg->base_params->max_event_log_size) {
IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
- next_entry, priv->cfg->max_event_log_size);
- next_entry = priv->cfg->max_event_log_size;
+ next_entry, priv->cfg->base_params->max_event_log_size);
+ next_entry = priv->cfg->base_params->max_event_log_size;
}
size = num_wraps ? capacity : next_entry;
@@ -1778,7 +1730,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
IWL_ERR(priv, "Microcode SW error detected. "
"Restarting 0x%X.\n", inta);
priv->isr_stats.sw++;
- priv->isr_stats.sw_err = inta;
iwl_irq_handle_error(priv);
handled |= CSR_INT_BIT_SW_ERR;
}
@@ -2522,6 +2473,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
{
int thermal_spin = 0;
u32 rfkill;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
@@ -2567,7 +2519,8 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
/* Enable timer to monitor the driver queues */
mod_timer(&priv->monitor_recover,
jiffies +
- msecs_to_jiffies(priv->cfg->monitor_recover_period));
+ msecs_to_jiffies(
+ priv->cfg->base_params->monitor_recover_period));
}
if (iwl_is_rfkill(priv))
@@ -2579,22 +2532,22 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
iwl_power_update_mode(priv, true);
- if (iwl_is_associated(priv)) {
+ if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
struct iwl3945_rxon_cmd *active_rxon =
- (struct iwl3945_rxon_cmd *)(&priv->active_rxon);
+ (struct iwl3945_rxon_cmd *)(&ctx->active);
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
/* Initialize our rx_config data */
- iwl_connection_init_rx_config(priv, NULL);
+ iwl_connection_init_rx_config(priv, ctx);
}
/* Configure Bluetooth device coexistence support */
priv->cfg->ops->hcmd->send_bt_config(priv);
/* Configure the adapter for unassociated operation */
- iwlcore_commit_rxon(priv);
+ iwl3945_commit_rxon(priv, ctx);
iwl3945_reg_txpower_periodic(priv);
@@ -2615,19 +2568,22 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv);
static void __iwl3945_down(struct iwl_priv *priv)
{
unsigned long flags;
- int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
- struct ieee80211_conf *conf = NULL;
+ int exit_pending;
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
- conf = ieee80211_get_hw_conf(priv->hw);
+ iwl_scan_cancel_timeout(priv, 200);
- if (!exit_pending)
- set_bit(STATUS_EXIT_PENDING, &priv->status);
+ exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+ /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
+ * to prevent rearm timer */
+ if (priv->cfg->ops->lib->recover_from_tx_stall)
+ del_timer_sync(&priv->monitor_recover);
/* Station information will now be cleared in device */
- iwl_clear_ucode_stations(priv);
- iwl_dealloc_bcast_station(priv);
+ iwl_clear_ucode_stations(priv, NULL);
+ iwl_dealloc_bcast_stations(priv);
iwl_clear_driver_stations(priv);
/* Unblock any waiting calls */
@@ -2681,14 +2637,14 @@ static void __iwl3945_down(struct iwl_priv *priv)
udelay(5);
/* Stop the device, and put it in low power state */
- priv->cfg->ops->lib->apm_ops.stop(priv);
+ iwl_apm_stop(priv);
exit:
memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
- priv->ibss_beacon = NULL;
+ if (priv->beacon_skb)
+ dev_kfree_skb(priv->beacon_skb);
+ priv->beacon_skb = NULL;
/* clear out any free frames */
iwl3945_clear_free_frames(priv);
@@ -2705,11 +2661,33 @@ static void iwl3945_down(struct iwl_priv *priv)
#define MAX_HW_RESTARTS 5
+static int iwl3945_alloc_bcast_station(struct iwl_priv *priv)
+{
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ unsigned long flags;
+ u8 sta_id;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ 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");
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return -EINVAL;
+ }
+
+ priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+ priv->stations[sta_id].used |= IWL_STA_BCAST;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return 0;
+}
+
static int __iwl3945_up(struct iwl_priv *priv)
{
int rc, i;
- rc = iwl_alloc_bcast_station(priv, false);
+ rc = iwl3945_alloc_bcast_station(priv);
if (rc)
return rc;
@@ -2861,7 +2839,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
}
-void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
@@ -2869,61 +2847,19 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
.flags = CMD_SIZE_HUGE,
};
struct iwl3945_scan_cmd *scan;
- struct ieee80211_conf *conf = NULL;
u8 n_probes = 0;
enum ieee80211_band band;
bool is_active = false;
+ int ret;
- conf = ieee80211_get_hw_conf(priv->hw);
-
- cancel_delayed_work(&priv->scan_check);
-
- if (!iwl_is_ready(priv)) {
- IWL_WARN(priv, "request scan called when driver not ready.\n");
- goto done;
- }
-
- /* Make sure the scan wasn't canceled before this queued work
- * was given the chance to run... */
- if (!test_bit(STATUS_SCANNING, &priv->status))
- goto done;
-
- /* This should never be called or scheduled if there is currently
- * a scan active in the hardware. */
- if (test_bit(STATUS_SCAN_HW, &priv->status)) {
- IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests "
- "Ignoring second request.\n");
- goto done;
- }
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
- goto done;
- }
-
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_HC(priv,
- "Scan request while abort pending. Queuing.\n");
- goto done;
- }
-
- if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
- goto done;
- }
-
- if (!test_bit(STATUS_READY, &priv->status)) {
- IWL_DEBUG_HC(priv,
- "Scan request while uninitialized. Queuing.\n");
- goto done;
- }
+ lockdep_assert_held(&priv->mutex);
if (!priv->scan_cmd) {
priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan_cmd) {
IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
- goto done;
+ return -ENOMEM;
}
}
scan = priv->scan_cmd;
@@ -2932,7 +2868,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
- if (iwl_is_associated(priv)) {
+ if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
u16 interval = 0;
u32 extra;
u32 suspend_time = 100;
@@ -2942,7 +2878,10 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
spin_lock_irqsave(&priv->lock, flags);
- interval = vif ? vif->bss_conf.beacon_int : 0;
+ if (priv->is_internal_short_scan)
+ interval = 0;
+ else
+ interval = vif->bss_conf.beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
scan->suspend_time = 0;
@@ -2990,7 +2929,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
/* We don't build a direct scan probe request; the uCode will do
* that based on the direct_mask added to each channel entry */
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
- scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
+ scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
/* flags + rate selection */
@@ -2999,37 +2938,39 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
case IEEE80211_BAND_2GHZ:
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
- scan->good_CRC_th = 0;
band = IEEE80211_BAND_2GHZ;
break;
case IEEE80211_BAND_5GHZ:
scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
- /*
- * If active scaning is requested but a certain channel
- * is marked passive, we can do active scanning if we
- * detect transmissions.
- */
- scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
- IWL_GOOD_CRC_TH_DISABLED;
band = IEEE80211_BAND_5GHZ;
break;
default:
IWL_WARN(priv, "Invalid scan band\n");
- goto done;
+ return -EIO;
}
+ /*
+ * If active scaning is requested but a certain channel
+ * is marked passive, we can do active scanning if we
+ * detect transmissions.
+ */
+ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+ IWL_GOOD_CRC_TH_DISABLED;
+
if (!priv->is_internal_short_scan) {
scan->tx_cmd.len = cpu_to_le16(
iwl_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
+ vif->addr,
priv->scan_request->ie,
priv->scan_request->ie_len,
IWL_MAX_SCAN_SIZE - sizeof(*scan)));
} else {
+ /* use bcast addr, will not be transmitted but must be valid */
scan->tx_cmd.len = cpu_to_le16(
iwl_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
- NULL, 0,
+ iwl_bcast_addr, NULL, 0,
IWL_MAX_SCAN_SIZE - sizeof(*scan)));
}
/* select Rx antennas */
@@ -3048,7 +2989,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
- goto done;
+ return -EIO;
}
cmd.len += le16_to_cpu(scan->tx_cmd.len) +
@@ -3057,25 +2998,22 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->len = cpu_to_le16(cmd.len);
set_bit(STATUS_SCAN_HW, &priv->status);
- if (iwl_send_cmd_sync(priv, &cmd))
- goto done;
-
- queue_delayed_work(priv->workqueue, &priv->scan_check,
- IWL_SCAN_CHECK_WATCHDOG);
+ ret = iwl_send_cmd_sync(priv, &cmd);
+ if (ret)
+ clear_bit(STATUS_SCAN_HW, &priv->status);
+ return ret;
+}
- return;
+void iwl3945_post_scan(struct iwl_priv *priv)
+{
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- done:
- /* can not perform scan make sure we clear scanning
- * bits from status so next scan request can be performed.
- * if we dont clear scanning status bit here all next scan
- * will fail
- */
- clear_bit(STATUS_SCAN_HW, &priv->status);
- clear_bit(STATUS_SCANNING, &priv->status);
-
- /* inform mac80211 scan aborted */
- queue_work(priv->workqueue, &priv->scan_completed);
+ /*
+ * Since setting the RXON may have been deferred while
+ * performing the scan, fire one off if needed
+ */
+ if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+ iwl3945_commit_rxon(priv, ctx);
}
static void iwl3945_bg_restart(struct work_struct *data)
@@ -3086,8 +3024,10 @@ static void iwl3945_bg_restart(struct work_struct *data)
return;
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+ struct iwl_rxon_context *ctx;
mutex_lock(&priv->mutex);
- priv->vif = NULL;
+ for_each_context(priv, ctx)
+ ctx->vif = NULL;
priv->is_open = 0;
mutex_unlock(&priv->mutex);
iwl3945_down(priv);
@@ -3121,6 +3061,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
int rc = 0;
struct ieee80211_conf *conf = NULL;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
if (!vif || !priv->is_open)
return;
@@ -3131,7 +3072,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
}
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
- vif->bss_conf.aid, priv->active_rxon.bssid_addr);
+ vif->bss_conf.aid, ctx->active.bssid_addr);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -3140,40 +3081,34 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
conf = ieee80211_get_hw_conf(priv->hw);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl3945_commit_rxon(priv, ctx);
- memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv, vif);
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
- sizeof(priv->rxon_timing), &priv->rxon_timing);
+ rc = iwl_send_rxon_timing(priv, ctx);
if (rc)
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
"Attempting to continue.\n");
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
- priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+ ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
vif->bss_conf.aid, vif->bss_conf.beacon_int);
- if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ if (vif->bss_conf.use_short_preamble)
+ ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
else
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
- if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
- if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+ if (vif->bss_conf.use_short_slot)
+ ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-
- if (vif->type == NL80211_IFTYPE_ADHOC)
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+ ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
}
- iwlcore_commit_rxon(priv);
+ iwl3945_commit_rxon(priv, ctx);
switch (vif->type) {
case NL80211_IFTYPE_STATION:
@@ -3272,15 +3207,6 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
priv->is_open = 0;
- if (iwl_is_ready_rf(priv)) {
- /* stop mac, cancel any scan request and clear
- * RXON_FILTER_ASSOC_MSK BIT
- */
- mutex_lock(&priv->mutex);
- iwl_scan_cancel_timeout(priv, 100);
- mutex_unlock(&priv->mutex);
- }
-
iwl3945_down(priv);
flush_workqueue(priv->workqueue);
@@ -3310,54 +3236,45 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
int rc = 0;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
/* The following should be done only at AP bring up */
- if (!(iwl_is_associated(priv))) {
+ if (!(iwl_is_associated(priv, IWL_RXON_CTX_BSS))) {
/* RXON - unassoc (to set timing command) */
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl3945_commit_rxon(priv, ctx);
/* RXON Timing */
- memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv, vif);
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
- sizeof(priv->rxon_timing),
- &priv->rxon_timing);
+ rc = iwl_send_rxon_timing(priv, ctx);
if (rc)
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
"Attempting to continue.\n");
- priv->staging_rxon.assoc_id = 0;
+ ctx->staging.assoc_id = 0;
- if (vif->bss_conf.assoc_capability &
- WLAN_CAPABILITY_SHORT_PREAMBLE)
- priv->staging_rxon.flags |=
+ if (vif->bss_conf.use_short_preamble)
+ ctx->staging.flags |=
RXON_FLG_SHORT_PREAMBLE_MSK;
else
- priv->staging_rxon.flags &=
+ ctx->staging.flags &=
~RXON_FLG_SHORT_PREAMBLE_MSK;
- if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
- if (vif->bss_conf.assoc_capability &
- WLAN_CAPABILITY_SHORT_SLOT_TIME)
- priv->staging_rxon.flags |=
+ if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+ if (vif->bss_conf.use_short_slot)
+ ctx->staging.flags |=
RXON_FLG_SHORT_SLOT_MSK;
else
- priv->staging_rxon.flags &=
- ~RXON_FLG_SHORT_SLOT_MSK;
-
- if (vif->type == NL80211_IFTYPE_ADHOC)
- priv->staging_rxon.flags &=
+ ctx->staging.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
}
/* restore RXON assoc */
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ iwl3945_commit_rxon(priv, ctx);
}
iwl3945_send_beacon_cmd(priv);
@@ -3383,20 +3300,13 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return -EOPNOTSUPP;
}
- static_key = !iwl_is_associated(priv);
+ static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS);
if (!static_key) {
- 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;
- }
- }
+ sta_id = iwl_sta_id_or_broadcast(
+ priv, &priv->contexts[IWL_RXON_CTX_BSS], sta);
+ if (sta_id == IWL_INVALID_STATION)
+ return -EINVAL;
}
mutex_lock(&priv->mutex);
@@ -3445,8 +3355,8 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
sta_priv->common.sta_id = IWL_INVALID_STATION;
- ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
- &sta_id);
+ ret = iwl_add_station_common(priv, &priv->contexts[IWL_RXON_CTX_BSS],
+ sta->addr, is_ap, sta, &sta_id);
if (ret) {
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
@@ -3465,6 +3375,56 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
return 0;
}
+
+static void iwl3945_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ u64 multicast)
+{
+ struct iwl_priv *priv = hw->priv;
+ __le32 filter_or = 0, filter_nand = 0;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+#define CHK(test, flag) do { \
+ if (*total_flags & (test)) \
+ filter_or |= (flag); \
+ else \
+ filter_nand |= (flag); \
+ } while (0)
+
+ IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
+ changed_flags, *total_flags);
+
+ CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
+ CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
+ CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
+
+#undef CHK
+
+ mutex_lock(&priv->mutex);
+
+ ctx->staging.filter_flags &= ~filter_nand;
+ ctx->staging.filter_flags |= filter_or;
+
+ /*
+ * Committing directly here breaks for some reason,
+ * but we'll eventually commit the filter flags
+ * change anyway.
+ */
+
+ mutex_unlock(&priv->mutex);
+
+ /*
+ * Receiving all multicast frames is always enabled by the
+ * default flags setup in iwl_connection_init_rx_config()
+ * since we currently do not support programming multicast
+ * filters into the device.
+ */
+ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+ FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
+}
+
+
/*****************************************************************************
*
* sysfs attributes
@@ -3558,8 +3518,9 @@ static ssize_t show_flags(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
+ return sprintf(buf, "0x%04X\n", ctx->active.flags);
}
static ssize_t store_flags(struct device *d,
@@ -3568,17 +3529,18 @@ static ssize_t store_flags(struct device *d,
{
struct iwl_priv *priv = dev_get_drvdata(d);
u32 flags = simple_strtoul(buf, NULL, 0);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
mutex_lock(&priv->mutex);
- if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
+ if (le32_to_cpu(ctx->staging.flags) != flags) {
/* Cancel any currently running scans... */
if (iwl_scan_cancel_timeout(priv, 100))
IWL_WARN(priv, "Could not cancel scan.\n");
else {
IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
flags);
- priv->staging_rxon.flags = cpu_to_le32(flags);
- iwlcore_commit_rxon(priv);
+ ctx->staging.flags = cpu_to_le32(flags);
+ iwl3945_commit_rxon(priv, ctx);
}
}
mutex_unlock(&priv->mutex);
@@ -3592,9 +3554,10 @@ static ssize_t show_filter_flags(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
return sprintf(buf, "0x%04X\n",
- le32_to_cpu(priv->active_rxon.filter_flags));
+ le32_to_cpu(ctx->active.filter_flags));
}
static ssize_t store_filter_flags(struct device *d,
@@ -3602,19 +3565,20 @@ static ssize_t store_filter_flags(struct device *d,
const char *buf, size_t count)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u32 filter_flags = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
- if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
+ if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
/* Cancel any currently running scans... */
if (iwl_scan_cancel_timeout(priv, 100))
IWL_WARN(priv, "Could not cancel scan.\n");
else {
IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
"0x%04X\n", filter_flags);
- priv->staging_rxon.filter_flags =
+ ctx->staging.filter_flags =
cpu_to_le32(filter_flags);
- iwlcore_commit_rxon(priv);
+ iwl3945_commit_rxon(priv, ctx);
}
}
mutex_unlock(&priv->mutex);
@@ -3662,8 +3626,9 @@ static ssize_t store_measurement(struct device *d,
const char *buf, size_t count)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct ieee80211_measurement_params params = {
- .channel = le16_to_cpu(priv->active_rxon.channel),
+ .channel = le16_to_cpu(ctx->active.channel),
.start_time = cpu_to_le64(priv->_3945.last_tsf),
.duration = cpu_to_le16(1),
};
@@ -3810,10 +3775,8 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
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);
+
+ iwl_setup_scan_deferred_work(priv);
iwl3945_hw_setup_deferred_work(priv);
@@ -3833,12 +3796,10 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
iwl3945_hw_cancel_deferred_work(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);
+
+ iwl_cancel_scan_deferred_work(priv);
}
static struct attribute *iwl3945_sysfs_entries[] = {
@@ -3870,7 +3831,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.add_interface = iwl_mac_add_interface,
.remove_interface = iwl_mac_remove_interface,
.config = iwl_mac_config,
- .configure_filter = iwl_configure_filter,
+ .configure_filter = iwl3945_configure_filter,
.set_key = iwl3945_mac_set_key,
.conf_tx = iwl_mac_conf_tx,
.reset_tsf = iwl_mac_reset_tsf,
@@ -3878,6 +3839,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.hw_scan = iwl_mac_hw_scan,
.sta_add = iwl3945_mac_sta_add,
.sta_remove = iwl_mac_sta_remove,
+ .tx_last_beacon = iwl_mac_tx_last_beacon,
};
static int iwl3945_init_drv(struct iwl_priv *priv)
@@ -3886,7 +3848,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
priv->retry_rate = 1;
- priv->ibss_beacon = NULL;
+ priv->beacon_skb = NULL;
spin_lock_init(&priv->sta_lock);
spin_lock_init(&priv->hcmd_lock);
@@ -3953,13 +3915,12 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SPECTRUM_MGMT;
- if (!priv->cfg->broken_powersave)
+ if (!priv->cfg->base_params->broken_powersave)
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
+ priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
WIPHY_FLAG_DISABLE_BEACON_HINTS;
@@ -3991,7 +3952,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- int err = 0;
+ int err = 0, i;
struct iwl_priv *priv;
struct ieee80211_hw *hw;
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
@@ -4006,19 +3967,40 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
* space for this driver's private structure */
hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
if (hw == NULL) {
- printk(KERN_ERR DRV_NAME "Can not allocate network device\n");
+ pr_err("Can not allocate network device\n");
err = -ENOMEM;
goto out;
}
priv = hw->priv;
SET_IEEE80211_DEV(hw, &pdev->dev);
+ priv->cmd_queue = IWL39_CMD_QUEUE_NUM;
+
+ /* 3945 has only one valid context */
+ priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
+
+ for (i = 0; i < NUM_IWL_RXON_CTX; i++)
+ priv->contexts[i].ctxid = i;
+
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
+ priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
+ priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+ priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
+ priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+ priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+ priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
+
/*
* Disabling hardware scan means that mac80211 will perform scans
* "the hard way", rather than using device's scan.
*/
if (iwl3945_mod_params.disable_hw_scan) {
- IWL_DEBUG_INFO(priv, "Disabling hw_scan\n");
+ IWL_ERR(priv, "sw scan support is deprecated\n");
iwl3945_hw_ops.hw_scan = NULL;
}
@@ -4028,15 +4010,15 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->pci_dev = pdev;
priv->inta_mask = CSR_INI_SET_MASK;
-#ifdef CONFIG_IWLWIFI_DEBUG
- atomic_set(&priv->restrict_refcnt, 0);
-#endif
if (iwl_alloc_traffic_mem(priv))
IWL_ERR(priv, "Not enough memory to generate traffic log\n");
/***************************
* 2. Initializing PCI bus
* *************************/
+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+ PCIE_LINK_STATE_CLKPM);
+
if (pci_enable_device(pdev)) {
err = -ENODEV;
goto out_ieee80211_free_hw;
@@ -4099,9 +4081,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
}
/* MAC Address location in EEPROM same for 3945/4965 */
eeprom = (struct iwl3945_eeprom *)priv->eeprom;
- memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN);
- IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr);
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+ IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address);
+ SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address);
/***********************
* 5. Setup HW Constants
@@ -4149,7 +4130,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
}
iwl_set_rxon_channel(priv,
- &priv->bands[IEEE80211_BAND_2GHZ].channels[5]);
+ &priv->bands[IEEE80211_BAND_2GHZ].channels[5],
+ &priv->contexts[IWL_RXON_CTX_BSS]);
iwl3945_setup_deferred_work(priv);
iwl3945_setup_rx_handlers(priv);
iwl_power_initialize(priv);
@@ -4230,7 +4212,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
* paths to avoid running iwl_down() at all before leaving driver.
* This (inexpensive) call *makes sure* device is reset.
*/
- priv->cfg->ops->lib->apm_ops.stop(priv);
+ iwl_apm_stop(priv);
/* make sure we flush any pending irq or
* tasklet for the driver
@@ -4274,8 +4256,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
iwl_free_channel_map(priv);
iwlcore_free_geos(priv);
kfree(priv->scan_cmd);
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
+ if (priv->beacon_skb)
+ dev_kfree_skb(priv->beacon_skb);
ieee80211_free_hw(priv->hw);
}
@@ -4302,19 +4284,18 @@ static int __init iwl3945_init(void)
{
int ret;
- printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
- printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+ pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ pr_info(DRV_COPYRIGHT "\n");
ret = iwl3945_rate_control_register();
if (ret) {
- printk(KERN_ERR DRV_NAME
- "Unable to register rate control algorithm: %d\n", ret);
+ pr_err("Unable to register rate control algorithm: %d\n", ret);
return ret;
}
ret = pci_register_driver(&iwl3945_driver);
if (ret) {
- printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n");
+ pr_err("Unable to initialize PCI module\n");
goto error_register;
}
@@ -4344,7 +4325,8 @@ MODULE_PARM_DESC(debug, "debug output mask");
#endif
module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan,
int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
+MODULE_PARM_DESC(disable_hw_scan,
+ "disable hardware scanning (default 0) (deprecated)");
module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO);
MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");