aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-10-23 12:15:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:24:53 -0500
commit2295c66b68ae160dde2e6e2dc4f3061105153bfc (patch)
tree9bfbaf309944d5f72bd36b291680ddf370733c1a /drivers/net/wireless
parent2d4e43c3c6783f956163c11568303b0390725e28 (diff)
iwlagn: new RXON processing for modern devices
In order to simplify the flow, and make new enhancements easier, separate out the RXON processing for modern AGN (5000 and newer) from RXON processing for the older 3945 and 4965 devices. Avoid changing these old ones to avoid regressions and move their code to a new file (iwl-legacy.c). 4965 gets the commit_rxon that used to be common for all AGN devices, but with removed PAN support. The new RXON processing is more central and does more work in committing, so that it is easier to follow. To make it more evident what is split out for legacy, split the necessary operations for that into a new struct iwl_legacy_ops. Those parts that still exist in the new AGN code don't need to be parametrized. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c318
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c562
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c385
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h34
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c531
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h30
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-legacy.c560
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-legacy.h74
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c30
17 files changed, 1631 insertions, 936 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 63edbe2e557f..ce05c260870e 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -2,6 +2,8 @@ obj-$(CONFIG_IWLWIFI) += iwlcore.o
2iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o 2iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
3iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o 3iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o
4iwlcore-objs += iwl-scan.o iwl-led.o 4iwlcore-objs += iwl-scan.o iwl-led.o
5iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o
6iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o
5iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o 7iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
6iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o 8iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
7 9
@@ -16,6 +18,7 @@ iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
16iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o 18iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
17 19
18iwlagn-$(CONFIG_IWL4965) += iwl-4965.o 20iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
21iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o
19iwlagn-$(CONFIG_IWL5000) += iwl-5000.o 22iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
20iwlagn-$(CONFIG_IWL5000) += iwl-6000.o 23iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
21iwlagn-$(CONFIG_IWL5000) += iwl-1000.o 24iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 4266c855a767..baedea8e4d04 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -211,14 +211,10 @@ static struct iwl_lib_ops iwl1000_lib = {
211 .calib_version = iwlagn_eeprom_calib_version, 211 .calib_version = iwlagn_eeprom_calib_version,
212 .query_addr = iwlagn_eeprom_query_addr, 212 .query_addr = iwlagn_eeprom_query_addr,
213 }, 213 },
214 .post_associate = iwl_post_associate,
215 .isr = iwl_isr_ict, 214 .isr = iwl_isr_ict,
216 .config_ap = iwl_config_ap,
217 .temp_ops = { 215 .temp_ops = {
218 .temperature = iwlagn_temperature, 216 .temperature = iwlagn_temperature,
219 }, 217 },
220 .manage_ibss_station = iwlagn_manage_ibss_station,
221 .update_bcast_stations = iwl_update_bcast_stations,
222 .debugfs_ops = { 218 .debugfs_ops = {
223 .rx_stats_read = iwl_ucode_rx_stats_read, 219 .rx_stats_read = iwl_ucode_rx_stats_read,
224 .tx_stats_read = iwl_ucode_tx_stats_read, 220 .tx_stats_read = iwl_ucode_tx_stats_read,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 95fed1158452..d9e676480269 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2726,10 +2726,7 @@ static struct iwl_lib_ops iwl3945_lib = {
2726 }, 2726 },
2727 .send_tx_power = iwl3945_send_tx_power, 2727 .send_tx_power = iwl3945_send_tx_power,
2728 .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, 2728 .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
2729 .post_associate = iwl3945_post_associate,
2730 .isr = iwl_isr_legacy, 2729 .isr = iwl_isr_legacy,
2731 .config_ap = iwl3945_config_ap,
2732 .manage_ibss_station = iwl3945_manage_ibss_station,
2733 .recover_from_tx_stall = iwl_bg_monitor_recover, 2730 .recover_from_tx_stall = iwl_bg_monitor_recover,
2734 .check_plcp_health = iwl3945_good_plcp_health, 2731 .check_plcp_health = iwl3945_good_plcp_health,
2735 2732
@@ -2740,6 +2737,12 @@ static struct iwl_lib_ops iwl3945_lib = {
2740 }, 2737 },
2741}; 2738};
2742 2739
2740static const struct iwl_legacy_ops iwl3945_legacy_ops = {
2741 .post_associate = iwl3945_post_associate,
2742 .config_ap = iwl3945_config_ap,
2743 .manage_ibss_station = iwl3945_manage_ibss_station,
2744};
2745
2743static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { 2746static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
2744 .get_hcmd_size = iwl3945_get_hcmd_size, 2747 .get_hcmd_size = iwl3945_get_hcmd_size,
2745 .build_addsta_hcmd = iwl3945_build_addsta_hcmd, 2748 .build_addsta_hcmd = iwl3945_build_addsta_hcmd,
@@ -2753,6 +2756,7 @@ static const struct iwl_ops iwl3945_ops = {
2753 .hcmd = &iwl3945_hcmd, 2756 .hcmd = &iwl3945_hcmd,
2754 .utils = &iwl3945_hcmd_utils, 2757 .utils = &iwl3945_hcmd_utils,
2755 .led = &iwl3945_led_ops, 2758 .led = &iwl3945_led_ops,
2759 .legacy = &iwl3945_legacy_ops,
2756 .ieee80211_ops = &iwl3945_hw_ops, 2760 .ieee80211_ops = &iwl3945_hw_ops,
2757}; 2761};
2758 2762
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index b27f07cbf355..3eef1eb74a78 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -264,10 +264,8 @@ void iwl3945_reply_statistics(struct iwl_priv *priv,
264 struct iwl_rx_mem_buffer *rxb); 264 struct iwl_rx_mem_buffer *rxb);
265extern void iwl3945_disable_events(struct iwl_priv *priv); 265extern void iwl3945_disable_events(struct iwl_priv *priv);
266extern int iwl4965_get_temperature(const struct iwl_priv *priv); 266extern int iwl4965_get_temperature(const struct iwl_priv *priv);
267extern void iwl3945_post_associate(struct iwl_priv *priv, 267extern void iwl3945_post_associate(struct iwl_priv *priv);
268 struct ieee80211_vif *vif); 268extern void iwl3945_config_ap(struct iwl_priv *priv);
269extern void iwl3945_config_ap(struct iwl_priv *priv,
270 struct ieee80211_vif *vif);
271 269
272extern int iwl3945_commit_rxon(struct iwl_priv *priv, 270extern int iwl3945_commit_rxon(struct iwl_priv *priv,
273 struct iwl_rxon_context *ctx); 271 struct iwl_rxon_context *ctx);
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 7921a910b34a..8f07964e4305 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -48,6 +48,7 @@
48#include "iwl-agn-led.h" 48#include "iwl-agn-led.h"
49#include "iwl-agn.h" 49#include "iwl-agn.h"
50#include "iwl-agn-debugfs.h" 50#include "iwl-agn-debugfs.h"
51#include "iwl-legacy.h"
51 52
52static int iwl4965_send_tx_power(struct iwl_priv *priv); 53static int iwl4965_send_tx_power(struct iwl_priv *priv);
53static int iwl4965_hw_get_temperature(struct iwl_priv *priv); 54static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
@@ -1443,6 +1444,142 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
1443 return ret; 1444 return ret;
1444} 1445}
1445 1446
1447static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
1448{
1449 /* cast away the const for active_rxon in this function */
1450 struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
1451 int ret;
1452 bool new_assoc =
1453 !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
1454
1455 if (!iwl_is_alive(priv))
1456 return -EBUSY;
1457
1458 if (!ctx->is_active)
1459 return 0;
1460
1461 /* always get timestamp with Rx frame */
1462 ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
1463
1464 ret = iwl_check_rxon_cmd(priv, ctx);
1465 if (ret) {
1466 IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
1467 return -EINVAL;
1468 }
1469
1470 /*
1471 * receive commit_rxon request
1472 * abort any previous channel switch if still in process
1473 */
1474 if (priv->switch_rxon.switch_in_progress &&
1475 (priv->switch_rxon.channel != ctx->staging.channel)) {
1476 IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
1477 le16_to_cpu(priv->switch_rxon.channel));
1478 iwl_chswitch_done(priv, false);
1479 }
1480
1481 /* If we don't need to send a full RXON, we can use
1482 * iwl_rxon_assoc_cmd which is used to reconfigure filter
1483 * and other flags for the current radio configuration. */
1484 if (!iwl_full_rxon_required(priv, ctx)) {
1485 ret = iwl_send_rxon_assoc(priv, ctx);
1486 if (ret) {
1487 IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
1488 return ret;
1489 }
1490
1491 memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
1492 iwl_print_rx_config_cmd(priv, ctx);
1493 return 0;
1494 }
1495
1496 /* If we are currently associated and the new config requires
1497 * an RXON_ASSOC and the new config wants the associated mask enabled,
1498 * we must clear the associated from the active configuration
1499 * before we apply the new config */
1500 if (iwl_is_associated_ctx(ctx) && new_assoc) {
1501 IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
1502 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
1503
1504 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
1505 sizeof(struct iwl_rxon_cmd),
1506 active_rxon);
1507
1508 /* If the mask clearing failed then we set
1509 * active_rxon back to what it was previously */
1510 if (ret) {
1511 active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
1512 IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
1513 return ret;
1514 }
1515 iwl_clear_ucode_stations(priv, ctx);
1516 iwl_restore_stations(priv, ctx);
1517 ret = iwl_restore_default_wep_keys(priv, ctx);
1518 if (ret) {
1519 IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
1520 return ret;
1521 }
1522 }
1523
1524 IWL_DEBUG_INFO(priv, "Sending RXON\n"
1525 "* with%s RXON_FILTER_ASSOC_MSK\n"
1526 "* channel = %d\n"
1527 "* bssid = %pM\n",
1528 (new_assoc ? "" : "out"),
1529 le16_to_cpu(ctx->staging.channel),
1530 ctx->staging.bssid_addr);
1531
1532 iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
1533
1534 /* Apply the new configuration
1535 * RXON unassoc clears the station table in uCode so restoration of
1536 * stations is needed after it (the RXON command) completes
1537 */
1538 if (!new_assoc) {
1539 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
1540 sizeof(struct iwl_rxon_cmd), &ctx->staging);
1541 if (ret) {
1542 IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
1543 return ret;
1544 }
1545 IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
1546 memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
1547 iwl_clear_ucode_stations(priv, ctx);
1548 iwl_restore_stations(priv, ctx);
1549 ret = iwl_restore_default_wep_keys(priv, ctx);
1550 if (ret) {
1551 IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
1552 return ret;
1553 }
1554 }
1555 if (new_assoc) {
1556 priv->start_calib = 0;
1557 /* Apply the new configuration
1558 * RXON assoc doesn't clear the station table in uCode,
1559 */
1560 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
1561 sizeof(struct iwl_rxon_cmd), &ctx->staging);
1562 if (ret) {
1563 IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
1564 return ret;
1565 }
1566 memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
1567 }
1568 iwl_print_rx_config_cmd(priv, ctx);
1569
1570 iwl_init_sensitivity(priv);
1571
1572 /* If we issue a new RXON command which required a tune then we must
1573 * send a new TXPOWER command or we won't be able to Tx any frames */
1574 ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
1575 if (ret) {
1576 IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
1577 return ret;
1578 }
1579
1580 return 0;
1581}
1582
1446static int iwl4965_hw_channel_switch(struct iwl_priv *priv, 1583static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
1447 struct ieee80211_channel_switch *ch_switch) 1584 struct ieee80211_channel_switch *ch_switch)
1448{ 1585{
@@ -2212,7 +2349,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
2212 2349
2213static struct iwl_hcmd_ops iwl4965_hcmd = { 2350static struct iwl_hcmd_ops iwl4965_hcmd = {
2214 .rxon_assoc = iwl4965_send_rxon_assoc, 2351 .rxon_assoc = iwl4965_send_rxon_assoc,
2215 .commit_rxon = iwlagn_commit_rxon, 2352 .commit_rxon = iwl4965_commit_rxon,
2216 .set_rxon_chain = iwlagn_set_rxon_chain, 2353 .set_rxon_chain = iwlagn_set_rxon_chain,
2217 .send_bt_config = iwl_send_bt_config, 2354 .send_bt_config = iwl_send_bt_config,
2218}; 2355};
@@ -2229,6 +2366,149 @@ static void iwl4965_post_scan(struct iwl_priv *priv)
2229 iwlcore_commit_rxon(priv, ctx); 2366 iwlcore_commit_rxon(priv, ctx);
2230} 2367}
2231 2368
2369static void iwl4965_post_associate(struct iwl_priv *priv)
2370{
2371 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
2372 struct ieee80211_vif *vif = ctx->vif;
2373 struct ieee80211_conf *conf = NULL;
2374 int ret = 0;
2375
2376 if (!vif || !priv->is_open)
2377 return;
2378
2379 if (vif->type == NL80211_IFTYPE_AP) {
2380 IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
2381 return;
2382 }
2383
2384 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
2385 return;
2386
2387 iwl_scan_cancel_timeout(priv, 200);
2388
2389 conf = ieee80211_get_hw_conf(priv->hw);
2390
2391 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2392 iwlcore_commit_rxon(priv, ctx);
2393
2394 ret = iwl_send_rxon_timing(priv, ctx);
2395 if (ret)
2396 IWL_WARN(priv, "RXON timing - "
2397 "Attempting to continue.\n");
2398
2399 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
2400
2401 iwl_set_rxon_ht(priv, &priv->current_ht_config);
2402
2403 if (priv->cfg->ops->hcmd->set_rxon_chain)
2404 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
2405
2406 ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
2407
2408 IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
2409 vif->bss_conf.aid, vif->bss_conf.beacon_int);
2410
2411 if (vif->bss_conf.use_short_preamble)
2412 ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
2413 else
2414 ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
2415
2416 if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
2417 if (vif->bss_conf.use_short_slot)
2418 ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
2419 else
2420 ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
2421 }
2422
2423 iwlcore_commit_rxon(priv, ctx);
2424
2425 IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
2426 vif->bss_conf.aid, ctx->active.bssid_addr);
2427
2428 switch (vif->type) {
2429 case NL80211_IFTYPE_STATION:
2430 break;
2431 case NL80211_IFTYPE_ADHOC:
2432 iwlagn_send_beacon_cmd(priv);
2433 break;
2434 default:
2435 IWL_ERR(priv, "%s Should not be called in %d mode\n",
2436 __func__, vif->type);
2437 break;
2438 }
2439
2440 /* the chain noise calibration will enabled PM upon completion
2441 * If chain noise has already been run, then we need to enable
2442 * power management here */
2443 if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
2444 iwl_power_update_mode(priv, false);
2445
2446 /* Enable Rx differential gain and sensitivity calibrations */
2447 iwl_chain_noise_reset(priv);
2448 priv->start_calib = 1;
2449}
2450
2451static void iwl4965_config_ap(struct iwl_priv *priv)
2452{
2453 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
2454 struct ieee80211_vif *vif = ctx->vif;
2455 int ret = 0;
2456
2457 lockdep_assert_held(&priv->mutex);
2458
2459 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
2460 return;
2461
2462 /* The following should be done only at AP bring up */
2463 if (!iwl_is_associated_ctx(ctx)) {
2464
2465 /* RXON - unassoc (to set timing command) */
2466 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2467 iwlcore_commit_rxon(priv, ctx);
2468
2469 /* RXON Timing */
2470 ret = iwl_send_rxon_timing(priv, ctx);
2471 if (ret)
2472 IWL_WARN(priv, "RXON timing failed - "
2473 "Attempting to continue.\n");
2474
2475 /* AP has all antennas */
2476 priv->chain_noise_data.active_chains =
2477 priv->hw_params.valid_rx_ant;
2478 iwl_set_rxon_ht(priv, &priv->current_ht_config);
2479 if (priv->cfg->ops->hcmd->set_rxon_chain)
2480 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
2481
2482 ctx->staging.assoc_id = 0;
2483
2484 if (vif->bss_conf.use_short_preamble)
2485 ctx->staging.flags |=
2486 RXON_FLG_SHORT_PREAMBLE_MSK;
2487 else
2488 ctx->staging.flags &=
2489 ~RXON_FLG_SHORT_PREAMBLE_MSK;
2490
2491 if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
2492 if (vif->bss_conf.use_short_slot)
2493 ctx->staging.flags |=
2494 RXON_FLG_SHORT_SLOT_MSK;
2495 else
2496 ctx->staging.flags &=
2497 ~RXON_FLG_SHORT_SLOT_MSK;
2498 }
2499 /* need to send beacon cmd before committing assoc RXON! */
2500 iwlagn_send_beacon_cmd(priv);
2501 /* restore RXON assoc */
2502 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
2503 iwlcore_commit_rxon(priv, ctx);
2504 }
2505 iwlagn_send_beacon_cmd(priv);
2506
2507 /* FIXME - we need to add code here to detect a totally new
2508 * configuration, reset the AP, unassoc, rxon timing, assoc,
2509 * clear sta table, add BCAST sta... */
2510}
2511
2232static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { 2512static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
2233 .get_hcmd_size = iwl4965_get_hcmd_size, 2513 .get_hcmd_size = iwl4965_get_hcmd_size,
2234 .build_addsta_hcmd = iwl4965_build_addsta_hcmd, 2514 .build_addsta_hcmd = iwl4965_build_addsta_hcmd,
@@ -2281,14 +2561,10 @@ static struct iwl_lib_ops iwl4965_lib = {
2281 }, 2561 },
2282 .send_tx_power = iwl4965_send_tx_power, 2562 .send_tx_power = iwl4965_send_tx_power,
2283 .update_chain_flags = iwl_update_chain_flags, 2563 .update_chain_flags = iwl_update_chain_flags,
2284 .post_associate = iwl_post_associate,
2285 .config_ap = iwl_config_ap,
2286 .isr = iwl_isr_legacy, 2564 .isr = iwl_isr_legacy,
2287 .temp_ops = { 2565 .temp_ops = {
2288 .temperature = iwl4965_temperature_calib, 2566 .temperature = iwl4965_temperature_calib,
2289 }, 2567 },
2290 .manage_ibss_station = iwlagn_manage_ibss_station,
2291 .update_bcast_stations = iwl_update_bcast_stations,
2292 .debugfs_ops = { 2568 .debugfs_ops = {
2293 .rx_stats_read = iwl_ucode_rx_stats_read, 2569 .rx_stats_read = iwl_ucode_rx_stats_read,
2294 .tx_stats_read = iwl_ucode_tx_stats_read, 2570 .tx_stats_read = iwl_ucode_tx_stats_read,
@@ -2300,12 +2576,42 @@ static struct iwl_lib_ops iwl4965_lib = {
2300 .check_plcp_health = iwl_good_plcp_health, 2576 .check_plcp_health = iwl_good_plcp_health,
2301}; 2577};
2302 2578
2579static const struct iwl_legacy_ops iwl4965_legacy_ops = {
2580 .post_associate = iwl4965_post_associate,
2581 .config_ap = iwl4965_config_ap,
2582 .manage_ibss_station = iwlagn_manage_ibss_station,
2583 .update_bcast_stations = iwl_update_bcast_stations,
2584};
2585
2586struct ieee80211_ops iwl4965_hw_ops = {
2587 .tx = iwlagn_mac_tx,
2588 .start = iwlagn_mac_start,
2589 .stop = iwlagn_mac_stop,
2590 .add_interface = iwl_mac_add_interface,
2591 .remove_interface = iwl_mac_remove_interface,
2592 .config = iwl_legacy_mac_config,
2593 .configure_filter = iwlagn_configure_filter,
2594 .set_key = iwlagn_mac_set_key,
2595 .update_tkip_key = iwlagn_mac_update_tkip_key,
2596 .conf_tx = iwl_mac_conf_tx,
2597 .reset_tsf = iwl_legacy_mac_reset_tsf,
2598 .bss_info_changed = iwl_legacy_mac_bss_info_changed,
2599 .ampdu_action = iwlagn_mac_ampdu_action,
2600 .hw_scan = iwl_mac_hw_scan,
2601 .sta_add = iwlagn_mac_sta_add,
2602 .sta_remove = iwl_mac_sta_remove,
2603 .channel_switch = iwlagn_mac_channel_switch,
2604 .flush = iwlagn_mac_flush,
2605 .tx_last_beacon = iwl_mac_tx_last_beacon,
2606};
2607
2303static const struct iwl_ops iwl4965_ops = { 2608static const struct iwl_ops iwl4965_ops = {
2304 .lib = &iwl4965_lib, 2609 .lib = &iwl4965_lib,
2305 .hcmd = &iwl4965_hcmd, 2610 .hcmd = &iwl4965_hcmd,
2306 .utils = &iwl4965_hcmd_utils, 2611 .utils = &iwl4965_hcmd_utils,
2307 .led = &iwlagn_led_ops, 2612 .led = &iwlagn_led_ops,
2308 .ieee80211_ops = &iwlagn_hw_ops, 2613 .legacy = &iwl4965_legacy_ops,
2614 .ieee80211_ops = &iwl4965_hw_ops,
2309}; 2615};
2310 2616
2311static struct iwl_base_params iwl4965_base_params = { 2617static struct iwl_base_params iwl4965_base_params = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 5f0327721692..e1f412f915ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -385,14 +385,10 @@ static struct iwl_lib_ops iwl5000_lib = {
385 .calib_version = iwlagn_eeprom_calib_version, 385 .calib_version = iwlagn_eeprom_calib_version,
386 .query_addr = iwlagn_eeprom_query_addr, 386 .query_addr = iwlagn_eeprom_query_addr,
387 }, 387 },
388 .post_associate = iwl_post_associate,
389 .isr = iwl_isr_ict, 388 .isr = iwl_isr_ict,
390 .config_ap = iwl_config_ap,
391 .temp_ops = { 389 .temp_ops = {
392 .temperature = iwlagn_temperature, 390 .temperature = iwlagn_temperature,
393 }, 391 },
394 .manage_ibss_station = iwlagn_manage_ibss_station,
395 .update_bcast_stations = iwl_update_bcast_stations,
396 .debugfs_ops = { 392 .debugfs_ops = {
397 .rx_stats_read = iwl_ucode_rx_stats_read, 393 .rx_stats_read = iwl_ucode_rx_stats_read,
398 .tx_stats_read = iwl_ucode_tx_stats_read, 394 .tx_stats_read = iwl_ucode_tx_stats_read,
@@ -453,14 +449,10 @@ static struct iwl_lib_ops iwl5150_lib = {
453 .calib_version = iwlagn_eeprom_calib_version, 449 .calib_version = iwlagn_eeprom_calib_version,
454 .query_addr = iwlagn_eeprom_query_addr, 450 .query_addr = iwlagn_eeprom_query_addr,
455 }, 451 },
456 .post_associate = iwl_post_associate,
457 .isr = iwl_isr_ict, 452 .isr = iwl_isr_ict,
458 .config_ap = iwl_config_ap,
459 .temp_ops = { 453 .temp_ops = {
460 .temperature = iwl5150_temperature, 454 .temperature = iwl5150_temperature,
461 }, 455 },
462 .manage_ibss_station = iwlagn_manage_ibss_station,
463 .update_bcast_stations = iwl_update_bcast_stations,
464 .debugfs_ops = { 456 .debugfs_ops = {
465 .rx_stats_read = iwl_ucode_rx_stats_read, 457 .rx_stats_read = iwl_ucode_rx_stats_read,
466 .tx_stats_read = iwl_ucode_tx_stats_read, 458 .tx_stats_read = iwl_ucode_tx_stats_read,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 85bde701351e..eacbce0d88b6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -328,14 +328,10 @@ static struct iwl_lib_ops iwl6000_lib = {
328 .query_addr = iwlagn_eeprom_query_addr, 328 .query_addr = iwlagn_eeprom_query_addr,
329 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, 329 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
330 }, 330 },
331 .post_associate = iwl_post_associate,
332 .isr = iwl_isr_ict, 331 .isr = iwl_isr_ict,
333 .config_ap = iwl_config_ap,
334 .temp_ops = { 332 .temp_ops = {
335 .temperature = iwlagn_temperature, 333 .temperature = iwlagn_temperature,
336 }, 334 },
337 .manage_ibss_station = iwlagn_manage_ibss_station,
338 .update_bcast_stations = iwl_update_bcast_stations,
339 .debugfs_ops = { 335 .debugfs_ops = {
340 .rx_stats_read = iwl_ucode_rx_stats_read, 336 .rx_stats_read = iwl_ucode_rx_stats_read,
341 .tx_stats_read = iwl_ucode_tx_stats_read, 337 .tx_stats_read = iwl_ucode_tx_stats_read,
@@ -399,14 +395,10 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
399 .query_addr = iwlagn_eeprom_query_addr, 395 .query_addr = iwlagn_eeprom_query_addr,
400 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, 396 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
401 }, 397 },
402 .post_associate = iwl_post_associate,
403 .isr = iwl_isr_ict, 398 .isr = iwl_isr_ict,
404 .config_ap = iwl_config_ap,
405 .temp_ops = { 399 .temp_ops = {
406 .temperature = iwlagn_temperature, 400 .temperature = iwlagn_temperature,
407 }, 401 },
408 .manage_ibss_station = iwlagn_manage_ibss_station,
409 .update_bcast_stations = iwl_update_bcast_stations,
410 .debugfs_ops = { 402 .debugfs_ops = {
411 .rx_stats_read = iwl_ucode_rx_stats_read, 403 .rx_stats_read = iwl_ucode_rx_stats_read,
412 .tx_stats_read = iwl_ucode_tx_stats_read, 404 .tx_stats_read = iwl_ucode_tx_stats_read,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
new file mode 100644
index 000000000000..58602457e415
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -0,0 +1,562 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
20 *
21 * Contact Information:
22 * Intel Linux Wireless <ilw@linux.intel.com>
23 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24 *
25 *****************************************************************************/
26
27#include "iwl-dev.h"
28#include "iwl-agn.h"
29#include "iwl-sta.h"
30#include "iwl-core.h"
31#include "iwl-agn-calib.h"
32
33static int iwlagn_disable_bss(struct iwl_priv *priv,
34 struct iwl_rxon_context *ctx,
35 struct iwl_rxon_cmd *send)
36{
37 __le32 old_filter = send->filter_flags;
38 int ret;
39
40 send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
41 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
42
43 send->filter_flags = old_filter;
44
45 if (ret)
46 IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret);
47
48 return ret;
49}
50
51static int iwlagn_disable_pan(struct iwl_priv *priv,
52 struct iwl_rxon_context *ctx,
53 struct iwl_rxon_cmd *send)
54{
55 __le32 old_filter = send->filter_flags;
56 u8 old_dev_type = send->dev_type;
57 int ret;
58
59 send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
60 send->dev_type = RXON_DEV_TYPE_P2P;
61 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
62
63 send->filter_flags = old_filter;
64 send->dev_type = old_dev_type;
65
66 if (ret)
67 IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
68
69 /* FIXME: WAIT FOR PAN DISABLE */
70 msleep(300);
71
72 return ret;
73}
74
75/**
76 * iwlagn_commit_rxon - commit staging_rxon to hardware
77 *
78 * The RXON command in staging_rxon is committed to the hardware and
79 * the active_rxon structure is updated with the new data. This
80 * function correctly transitions out of the RXON_ASSOC_MSK state if
81 * a HW tune is required based on the RXON structure changes.
82 */
83int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
84{
85 /* cast away the const for active_rxon in this function */
86 struct iwl_rxon_cmd *active = (void *)&ctx->active;
87 bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
88 bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
89 int ret;
90
91 lockdep_assert_held(&priv->mutex);
92
93 if (!iwl_is_alive(priv))
94 return -EBUSY;
95
96 /* This function hardcodes a bunch of dual-mode assumptions */
97 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
98
99 if (!ctx->is_active)
100 return 0;
101
102 /* always get timestamp with Rx frame */
103 ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
104
105 if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
106 !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
107 ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
108 else
109 ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
110
111 ret = iwl_check_rxon_cmd(priv, ctx);
112 if (ret) {
113 IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
114 return -EINVAL;
115 }
116
117 /*
118 * receive commit_rxon request
119 * abort any previous channel switch if still in process
120 */
121 if (priv->switch_rxon.switch_in_progress &&
122 (priv->switch_rxon.channel != ctx->staging.channel)) {
123 IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
124 le16_to_cpu(priv->switch_rxon.channel));
125 iwl_chswitch_done(priv, false);
126 }
127
128 /*
129 * If we don't need to send a full RXON, we can use
130 * iwl_rxon_assoc_cmd which is used to reconfigure filter
131 * and other flags for the current radio configuration.
132 */
133 if (!iwl_full_rxon_required(priv, ctx)) {
134 ret = iwl_send_rxon_assoc(priv, ctx);
135 if (ret) {
136 IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
137 return ret;
138 }
139
140 memcpy(active, &ctx->staging, sizeof(*active));
141 iwl_print_rx_config_cmd(priv, ctx);
142 return 0;
143 }
144
145 if (priv->cfg->ops->hcmd->set_pan_params) {
146 ret = priv->cfg->ops->hcmd->set_pan_params(priv);
147 if (ret)
148 return ret;
149 }
150
151 iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
152
153 IWL_DEBUG_INFO(priv,
154 "Going to commit RXON\n"
155 " * with%s RXON_FILTER_ASSOC_MSK\n"
156 " * channel = %d\n"
157 " * bssid = %pM\n",
158 (new_assoc ? "" : "out"),
159 le16_to_cpu(ctx->staging.channel),
160 ctx->staging.bssid_addr);
161
162 /*
163 * If we are currently associated and the new config is also
164 * going to be associated, OR if the new config is simply not
165 * associated, clear associated.
166 */
167 if ((old_assoc && new_assoc) || !new_assoc) {
168 struct iwl_rxon_cmd *send = active;
169
170 if (!new_assoc)
171 send = &ctx->staging;
172
173 if (ctx->ctxid == IWL_RXON_CTX_BSS)
174 ret = iwlagn_disable_bss(priv, ctx, send);
175 else
176 ret = iwlagn_disable_pan(priv, ctx, send);
177 if (ret)
178 return ret;
179
180 if (send != active)
181 memcpy(active, send, sizeof(*active));
182
183 /*
184 * Un-assoc RXON clears the station table and WEP
185 * keys, so we have to restore those afterwards.
186 */
187 iwl_clear_ucode_stations(priv, ctx);
188 iwl_restore_stations(priv, ctx);
189 ret = iwl_restore_default_wep_keys(priv, ctx);
190 if (ret) {
191 IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
192 return ret;
193 }
194 }
195
196 /* RXON timing must be before associated RXON */
197 ret = iwl_send_rxon_timing(priv, ctx);
198 if (ret) {
199 IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
200 return ret;
201 }
202
203 if (new_assoc) {
204 if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP ||
205 ctx->vif->type == NL80211_IFTYPE_ADHOC)) {
206 /*
207 * We'll run into this code path when beaconing is
208 * enabled, but then we also need to send the beacon
209 * to the device.
210 */
211 dev_kfree_skb(priv->beacon_skb);
212 priv->beacon_skb = ieee80211_beacon_get(priv->hw,
213 ctx->vif);
214 iwlagn_send_beacon_cmd(priv);
215 }
216
217 priv->start_calib = 0;
218 /*
219 * Apply the new configuration.
220 *
221 * Associated RXON doesn't clear the station table in uCode,
222 * so we don't need to restore stations etc. after this.
223 */
224 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
225 sizeof(struct iwl_rxon_cmd), &ctx->staging);
226 if (ret) {
227 IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
228 return ret;
229 }
230 memcpy(active, &ctx->staging, sizeof(*active));
231 }
232
233 iwl_print_rx_config_cmd(priv, ctx);
234
235 iwl_init_sensitivity(priv);
236
237 /*
238 * If we issue a new RXON command which required a tune then we must
239 * send a new TXPOWER command or we won't be able to Tx any frames.
240 *
241 * FIXME: which RXON requires a tune? Can we optimise this out in
242 * some cases?
243 */
244 ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
245 if (ret) {
246 IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
247 return ret;
248 }
249
250 return 0;
251}
252
253int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
254{
255 struct iwl_priv *priv = hw->priv;
256 struct iwl_rxon_context *ctx;
257 struct ieee80211_conf *conf = &hw->conf;
258 struct ieee80211_channel *channel = conf->channel;
259 const struct iwl_channel_info *ch_info;
260 int ret = 0;
261
262 IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
263
264 mutex_lock(&priv->mutex);
265
266 if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
267 IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
268 goto out;
269 }
270
271 if (!iwl_is_ready(priv)) {
272 IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
273 goto out;
274 }
275
276 if (changed & (IEEE80211_CONF_CHANGE_SMPS |
277 IEEE80211_CONF_CHANGE_CHANNEL)) {
278 /* mac80211 uses static for non-HT which is what we want */
279 priv->current_ht_config.smps = conf->smps_mode;
280
281 /*
282 * Recalculate chain counts.
283 *
284 * If monitor mode is enabled then mac80211 will
285 * set up the SM PS mode to OFF if an HT channel is
286 * configured.
287 */
288 if (priv->cfg->ops->hcmd->set_rxon_chain)
289 for_each_context(priv, ctx)
290 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
291 }
292
293 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
294 unsigned long flags;
295
296 ch_info = iwl_get_channel_info(priv, channel->band,
297 channel->hw_value);
298 if (!is_channel_valid(ch_info)) {
299 IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
300 ret = -EINVAL;
301 goto out;
302 }
303
304 spin_lock_irqsave(&priv->lock, flags);
305
306 for_each_context(priv, ctx) {
307 /* Configure HT40 channels */
308 ctx->ht.enabled = conf_is_ht(conf);
309 if (ctx->ht.enabled) {
310 if (conf_is_ht40_minus(conf)) {
311 ctx->ht.extension_chan_offset =
312 IEEE80211_HT_PARAM_CHA_SEC_BELOW;
313 ctx->ht.is_40mhz = true;
314 } else if (conf_is_ht40_plus(conf)) {
315 ctx->ht.extension_chan_offset =
316 IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
317 ctx->ht.is_40mhz = true;
318 } else {
319 ctx->ht.extension_chan_offset =
320 IEEE80211_HT_PARAM_CHA_SEC_NONE;
321 ctx->ht.is_40mhz = false;
322 }
323 } else
324 ctx->ht.is_40mhz = false;
325
326 /*
327 * Default to no protection. Protection mode will
328 * later be set from BSS config in iwl_ht_conf
329 */
330 ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
331
332 /* if we are switching from ht to 2.4 clear flags
333 * from any ht related info since 2.4 does not
334 * support ht */
335 if (le16_to_cpu(ctx->staging.channel) !=
336 channel->hw_value)
337 ctx->staging.flags = 0;
338
339 iwl_set_rxon_channel(priv, channel, ctx);
340 iwl_set_rxon_ht(priv, &priv->current_ht_config);
341
342 iwl_set_flags_for_band(priv, ctx, channel->band,
343 ctx->vif);
344 }
345
346 spin_unlock_irqrestore(&priv->lock, flags);
347
348 iwl_update_bcast_stations(priv);
349
350 /*
351 * The list of supported rates and rate mask can be different
352 * for each band; since the band may have changed, reset
353 * the rate mask to what mac80211 lists.
354 */
355 iwl_set_rate(priv);
356 }
357
358 if (changed & (IEEE80211_CONF_CHANGE_PS |
359 IEEE80211_CONF_CHANGE_IDLE)) {
360 ret = iwl_power_update_mode(priv, false);
361 if (ret)
362 IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
363 }
364
365 if (changed & IEEE80211_CONF_CHANGE_POWER) {
366 IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
367 priv->tx_power_user_lmt, conf->power_level);
368
369 iwl_set_tx_power(priv, conf->power_level, false);
370 }
371
372 for_each_context(priv, ctx) {
373 if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
374 continue;
375 iwlagn_commit_rxon(priv, ctx);
376 }
377 out:
378 mutex_unlock(&priv->mutex);
379 return ret;
380}
381
382static void iwlagn_update_qos(struct iwl_priv *priv,
383 struct iwl_rxon_context *ctx)
384{
385 int ret;
386
387 if (!ctx->is_active)
388 return;
389
390 ctx->qos_data.def_qos_parm.qos_flags = 0;
391
392 if (ctx->qos_data.qos_active)
393 ctx->qos_data.def_qos_parm.qos_flags |=
394 QOS_PARAM_FLG_UPDATE_EDCA_MSK;
395
396 if (ctx->ht.enabled)
397 ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
398
399 IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
400 ctx->qos_data.qos_active,
401 ctx->qos_data.def_qos_parm.qos_flags);
402
403 ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
404 sizeof(struct iwl_qosparam_cmd),
405 &ctx->qos_data.def_qos_parm);
406 if (ret)
407 IWL_ERR(priv, "Failed to update QoS\n");
408}
409
410static void iwlagn_check_needed_chains(struct iwl_priv *priv,
411 struct iwl_rxon_context *ctx,
412 struct ieee80211_bss_conf *bss_conf)
413{
414 struct ieee80211_vif *vif = ctx->vif;
415 struct iwl_rxon_context *tmp;
416 struct ieee80211_sta *sta;
417 struct iwl_ht_config *ht_conf = &priv->current_ht_config;
418 bool need_multiple;
419
420 lockdep_assert_held(&priv->mutex);
421
422 switch (vif->type) {
423 case NL80211_IFTYPE_STATION:
424 rcu_read_lock();
425 sta = ieee80211_find_sta(vif, bss_conf->bssid);
426 if (sta) {
427 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
428 int maxstreams;
429
430 maxstreams = (ht_cap->mcs.tx_params &
431 IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
432 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
433 maxstreams += 1;
434
435 if ((ht_cap->mcs.rx_mask[1] == 0) &&
436 (ht_cap->mcs.rx_mask[2] == 0))
437 need_multiple = false;
438 if (maxstreams <= 1)
439 need_multiple = true;
440 } else {
441 /*
442 * If at all, this can only happen through a race
443 * when the AP disconnects us while we're still
444 * setting up the connection, in that case mac80211
445 * will soon tell us about that.
446 */
447 need_multiple = false;
448 }
449 rcu_read_unlock();
450 break;
451 case NL80211_IFTYPE_ADHOC:
452 /* currently */
453 need_multiple = false;
454 break;
455 default:
456 /* only AP really */
457 need_multiple = true;
458 break;
459 }
460
461 ctx->ht_need_multiple_chains = need_multiple;
462
463 if (!need_multiple) {
464 /* check all contexts */
465 for_each_context(priv, tmp) {
466 if (!tmp->vif)
467 continue;
468 if (tmp->ht_need_multiple_chains) {
469 need_multiple = true;
470 break;
471 }
472 }
473 }
474
475 ht_conf->single_chain_sufficient = !need_multiple;
476}
477
478void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
479 struct ieee80211_vif *vif,
480 struct ieee80211_bss_conf *bss_conf,
481 u32 changes)
482{
483 struct iwl_priv *priv = hw->priv;
484 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
485 int ret;
486 bool force = false;
487
488 mutex_lock(&priv->mutex);
489
490 if (changes & BSS_CHANGED_BEACON_INT)
491 force = true;
492
493 if (changes & BSS_CHANGED_QOS) {
494 ctx->qos_data.qos_active = bss_conf->qos;
495 iwlagn_update_qos(priv, ctx);
496 }
497
498 ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
499 if (vif->bss_conf.use_short_preamble)
500 ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
501 else
502 ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
503
504 if (changes & BSS_CHANGED_ASSOC) {
505 if (bss_conf->assoc) {
506 iwl_led_associate(priv);
507 priv->timestamp = bss_conf->timestamp;
508 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
509 } else {
510 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
511 iwl_led_disassociate(priv);
512 }
513 }
514
515 if (ctx->ht.enabled) {
516 ctx->ht.protection = bss_conf->ht_operation_mode &
517 IEEE80211_HT_OP_MODE_PROTECTION;
518 ctx->ht.non_gf_sta_present = !!(bss_conf->ht_operation_mode &
519 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
520 iwlagn_check_needed_chains(priv, ctx, bss_conf);
521 }
522
523 if (priv->cfg->ops->hcmd->set_rxon_chain)
524 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
525
526 if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
527 ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
528 else
529 ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
530
531 if (bss_conf->use_cts_prot)
532 ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
533 else
534 ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
535
536 memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
537
538 if (vif->type == NL80211_IFTYPE_AP ||
539 vif->type == NL80211_IFTYPE_ADHOC) {
540 if (vif->bss_conf.enable_beacon) {
541 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
542 priv->beacon_ctx = ctx;
543 } else {
544 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
545 priv->beacon_ctx = NULL;
546 }
547 }
548
549 if (force || memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
550 iwlagn_commit_rxon(priv, ctx);
551
552 if (changes & BSS_CHANGED_IBSS) {
553 ret = iwlagn_manage_ibss_station(priv, vif,
554 bss_conf->ibss_joined);
555 if (ret)
556 IWL_ERR(priv, "failed to %s IBSS station %pM\n",
557 bss_conf->ibss_joined ? "add" : "remove",
558 bss_conf->bssid);
559 }
560
561 mutex_unlock(&priv->mutex);
562}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 3d1f6831cc20..1050f31d90a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -90,153 +90,6 @@ MODULE_ALIAS("iwl4965");
90static int iwlagn_ant_coupling; 90static int iwlagn_ant_coupling;
91static bool iwlagn_bt_ch_announce = 1; 91static bool iwlagn_bt_ch_announce = 1;
92 92
93/**
94 * iwlagn_commit_rxon - commit staging_rxon to hardware
95 *
96 * The RXON command in staging_rxon is committed to the hardware and
97 * the active_rxon structure is updated with the new data. This
98 * function correctly transitions out of the RXON_ASSOC_MSK state if
99 * a HW tune is required based on the RXON structure changes.
100 */
101int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
102{
103 /* cast away the const for active_rxon in this function */
104 struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
105 int ret;
106 bool new_assoc =
107 !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
108
109 if (!iwl_is_alive(priv))
110 return -EBUSY;
111
112 if (!ctx->is_active)
113 return 0;
114
115 /* always get timestamp with Rx frame */
116 ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
117
118 ret = iwl_check_rxon_cmd(priv, ctx);
119 if (ret) {
120 IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
121 return -EINVAL;
122 }
123
124 /*
125 * receive commit_rxon request
126 * abort any previous channel switch if still in process
127 */
128 if (priv->switch_rxon.switch_in_progress &&
129 (priv->switch_rxon.channel != ctx->staging.channel)) {
130 IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
131 le16_to_cpu(priv->switch_rxon.channel));
132 iwl_chswitch_done(priv, false);
133 }
134
135 /* If we don't need to send a full RXON, we can use
136 * iwl_rxon_assoc_cmd which is used to reconfigure filter
137 * and other flags for the current radio configuration. */
138 if (!iwl_full_rxon_required(priv, ctx)) {
139 ret = iwl_send_rxon_assoc(priv, ctx);
140 if (ret) {
141 IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
142 return ret;
143 }
144
145 memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
146 iwl_print_rx_config_cmd(priv, ctx);
147 return 0;
148 }
149
150 /* If we are currently associated and the new config requires
151 * an RXON_ASSOC and the new config wants the associated mask enabled,
152 * we must clear the associated from the active configuration
153 * before we apply the new config */
154 if (iwl_is_associated_ctx(ctx) && new_assoc) {
155 IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
156 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
157
158 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
159 sizeof(struct iwl_rxon_cmd),
160 active_rxon);
161
162 /* If the mask clearing failed then we set
163 * active_rxon back to what it was previously */
164 if (ret) {
165 active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
166 IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
167 return ret;
168 }
169 iwl_clear_ucode_stations(priv, ctx);
170 iwl_restore_stations(priv, ctx);
171 ret = iwl_restore_default_wep_keys(priv, ctx);
172 if (ret) {
173 IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
174 return ret;
175 }
176 }
177
178 IWL_DEBUG_INFO(priv, "Sending RXON\n"
179 "* with%s RXON_FILTER_ASSOC_MSK\n"
180 "* channel = %d\n"
181 "* bssid = %pM\n",
182 (new_assoc ? "" : "out"),
183 le16_to_cpu(ctx->staging.channel),
184 ctx->staging.bssid_addr);
185
186 iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
187
188 if (priv->cfg->ops->hcmd->set_pan_params) {
189 ret = priv->cfg->ops->hcmd->set_pan_params(priv);
190 if (ret)
191 return ret;
192 }
193
194 /* Apply the new configuration
195 * RXON unassoc clears the station table in uCode so restoration of
196 * stations is needed after it (the RXON command) completes
197 */
198 if (!new_assoc) {
199 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
200 sizeof(struct iwl_rxon_cmd), &ctx->staging);
201 if (ret) {
202 IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
203 return ret;
204 }
205 IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
206 memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
207 iwl_clear_ucode_stations(priv, ctx);
208 iwl_restore_stations(priv, ctx);
209 ret = iwl_restore_default_wep_keys(priv, ctx);
210 if (ret) {
211 IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
212 return ret;
213 }
214 }
215 if (new_assoc) {
216 priv->start_calib = 0;
217 /* Apply the new configuration
218 * RXON assoc doesn't clear the station table in uCode,
219 */
220 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
221 sizeof(struct iwl_rxon_cmd), &ctx->staging);
222 if (ret) {
223 IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
224 return ret;
225 }
226 memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
227 }
228 iwl_print_rx_config_cmd(priv, ctx);
229
230 iwl_init_sensitivity(priv);
231
232 /* If we issue a new RXON command which required a tune then we must
233 * send a new TXPOWER command or we won't be able to Tx any frames */
234 ret = priv->cfg->ops->lib->send_tx_power(priv);
235 if (ret)
236 IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
237 return ret;
238}
239
240void iwl_update_chain_flags(struct iwl_priv *priv) 93void iwl_update_chain_flags(struct iwl_priv *priv)
241{ 94{
242 struct iwl_rxon_context *ctx; 95 struct iwl_rxon_context *ctx;
@@ -394,7 +247,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
394 247
395 return sizeof(*tx_beacon_cmd) + frame_size; 248 return sizeof(*tx_beacon_cmd) + frame_size;
396} 249}
397static int iwl_send_beacon_cmd(struct iwl_priv *priv) 250
251int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
398{ 252{
399 struct iwl_frame *frame; 253 struct iwl_frame *frame;
400 unsigned int frame_size; 254 unsigned int frame_size;
@@ -644,7 +498,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
644 498
645 priv->beacon_skb = beacon; 499 priv->beacon_skb = beacon;
646 500
647 iwl_send_beacon_cmd(priv); 501 iwlagn_send_beacon_cmd(priv);
648 out: 502 out:
649 mutex_unlock(&priv->mutex); 503 mutex_unlock(&priv->mutex);
650} 504}
@@ -3292,92 +3146,6 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
3292 mutex_unlock(&priv->mutex); 3146 mutex_unlock(&priv->mutex);
3293} 3147}
3294 3148
3295#define IWL_DELAY_NEXT_SCAN (HZ*2)
3296
3297void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
3298{
3299 struct iwl_rxon_context *ctx;
3300 struct ieee80211_conf *conf = NULL;
3301 int ret = 0;
3302
3303 if (!vif || !priv->is_open)
3304 return;
3305
3306 ctx = iwl_rxon_ctx_from_vif(vif);
3307
3308 if (vif->type == NL80211_IFTYPE_AP) {
3309 IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
3310 return;
3311 }
3312
3313 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3314 return;
3315
3316 iwl_scan_cancel_timeout(priv, 200);
3317
3318 conf = ieee80211_get_hw_conf(priv->hw);
3319
3320 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
3321 iwlcore_commit_rxon(priv, ctx);
3322
3323 ret = iwl_send_rxon_timing(priv, ctx);
3324 if (ret)
3325 IWL_WARN(priv, "RXON timing - "
3326 "Attempting to continue.\n");
3327
3328 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
3329
3330 iwl_set_rxon_ht(priv, &priv->current_ht_config);
3331
3332 if (priv->cfg->ops->hcmd->set_rxon_chain)
3333 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
3334
3335 ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
3336
3337 IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
3338 vif->bss_conf.aid, vif->bss_conf.beacon_int);
3339
3340 if (vif->bss_conf.use_short_preamble)
3341 ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
3342 else
3343 ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
3344
3345 if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
3346 if (vif->bss_conf.use_short_slot)
3347 ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
3348 else
3349 ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
3350 }
3351
3352 iwlcore_commit_rxon(priv, ctx);
3353
3354 IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
3355 vif->bss_conf.aid, ctx->active.bssid_addr);
3356
3357 switch (vif->type) {
3358 case NL80211_IFTYPE_STATION:
3359 break;
3360 case NL80211_IFTYPE_ADHOC:
3361 iwl_send_beacon_cmd(priv);
3362 break;
3363 default:
3364 IWL_ERR(priv, "%s Should not be called in %d mode\n",
3365 __func__, vif->type);
3366 break;
3367 }
3368
3369 /* the chain noise calibration will enabled PM upon completion
3370 * If chain noise has already been run, then we need to enable
3371 * power management here */
3372 if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
3373 iwl_power_update_mode(priv, false);
3374
3375 /* Enable Rx differential gain and sensitivity calibrations */
3376 iwl_chain_noise_reset(priv);
3377 priv->start_calib = 1;
3378
3379}
3380
3381/***************************************************************************** 3149/*****************************************************************************
3382 * 3150 *
3383 * mac80211 entry point functions 3151 * mac80211 entry point functions
@@ -3457,7 +3225,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
3457} 3225}
3458 3226
3459 3227
3460static int iwl_mac_start(struct ieee80211_hw *hw) 3228int iwlagn_mac_start(struct ieee80211_hw *hw)
3461{ 3229{
3462 struct iwl_priv *priv = hw->priv; 3230 struct iwl_priv *priv = hw->priv;
3463 int ret; 3231 int ret;
@@ -3498,7 +3266,7 @@ out:
3498 return 0; 3266 return 0;
3499} 3267}
3500 3268
3501static void iwl_mac_stop(struct ieee80211_hw *hw) 3269void iwlagn_mac_stop(struct ieee80211_hw *hw)
3502{ 3270{
3503 struct iwl_priv *priv = hw->priv; 3271 struct iwl_priv *priv = hw->priv;
3504 3272
@@ -3520,7 +3288,7 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
3520 IWL_DEBUG_MAC80211(priv, "leave\n"); 3288 IWL_DEBUG_MAC80211(priv, "leave\n");
3521} 3289}
3522 3290
3523static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 3291int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
3524{ 3292{
3525 struct iwl_priv *priv = hw->priv; 3293 struct iwl_priv *priv = hw->priv;
3526 3294
@@ -3536,73 +3304,12 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
3536 return NETDEV_TX_OK; 3304 return NETDEV_TX_OK;
3537} 3305}
3538 3306
3539void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) 3307void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
3540{ 3308 struct ieee80211_vif *vif,
3541 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); 3309 struct ieee80211_key_conf *keyconf,
3542 int ret = 0; 3310 struct ieee80211_sta *sta,
3543 3311 u32 iv32, u16 *phase1key)
3544 lockdep_assert_held(&priv->mutex);
3545
3546 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3547 return;
3548
3549 /* The following should be done only at AP bring up */
3550 if (!iwl_is_associated_ctx(ctx)) {
3551
3552 /* RXON - unassoc (to set timing command) */
3553 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
3554 iwlcore_commit_rxon(priv, ctx);
3555
3556 /* RXON Timing */
3557 ret = iwl_send_rxon_timing(priv, ctx);
3558 if (ret)
3559 IWL_WARN(priv, "RXON timing failed - "
3560 "Attempting to continue.\n");
3561
3562 /* AP has all antennas */
3563 priv->chain_noise_data.active_chains =
3564 priv->hw_params.valid_rx_ant;
3565 iwl_set_rxon_ht(priv, &priv->current_ht_config);
3566 if (priv->cfg->ops->hcmd->set_rxon_chain)
3567 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
3568
3569 ctx->staging.assoc_id = 0;
3570
3571 if (vif->bss_conf.use_short_preamble)
3572 ctx->staging.flags |=
3573 RXON_FLG_SHORT_PREAMBLE_MSK;
3574 else
3575 ctx->staging.flags &=
3576 ~RXON_FLG_SHORT_PREAMBLE_MSK;
3577
3578 if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
3579 if (vif->bss_conf.use_short_slot)
3580 ctx->staging.flags |=
3581 RXON_FLG_SHORT_SLOT_MSK;
3582 else
3583 ctx->staging.flags &=
3584 ~RXON_FLG_SHORT_SLOT_MSK;
3585 }
3586 /* need to send beacon cmd before committing assoc RXON! */
3587 iwl_send_beacon_cmd(priv);
3588 /* restore RXON assoc */
3589 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
3590 iwlcore_commit_rxon(priv, ctx);
3591 }
3592 iwl_send_beacon_cmd(priv);
3593
3594 /* FIXME - we need to add code here to detect a totally new
3595 * configuration, reset the AP, unassoc, rxon timing, assoc,
3596 * clear sta table, add BCAST sta... */
3597}
3598
3599static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
3600 struct ieee80211_vif *vif,
3601 struct ieee80211_key_conf *keyconf,
3602 struct ieee80211_sta *sta,
3603 u32 iv32, u16 *phase1key)
3604{ 3312{
3605
3606 struct iwl_priv *priv = hw->priv; 3313 struct iwl_priv *priv = hw->priv;
3607 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; 3314 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
3608 3315
@@ -3614,10 +3321,9 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
3614 IWL_DEBUG_MAC80211(priv, "leave\n"); 3321 IWL_DEBUG_MAC80211(priv, "leave\n");
3615} 3322}
3616 3323
3617static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 3324int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3618 struct ieee80211_vif *vif, 3325 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
3619 struct ieee80211_sta *sta, 3326 struct ieee80211_key_conf *key)
3620 struct ieee80211_key_conf *key)
3621{ 3327{
3622 struct iwl_priv *priv = hw->priv; 3328 struct iwl_priv *priv = hw->priv;
3623 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; 3329 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
@@ -3684,10 +3390,10 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3684 return ret; 3390 return ret;
3685} 3391}
3686 3392
3687static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, 3393int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
3688 struct ieee80211_vif *vif, 3394 struct ieee80211_vif *vif,
3689 enum ieee80211_ampdu_mlme_action action, 3395 enum ieee80211_ampdu_mlme_action action,
3690 struct ieee80211_sta *sta, u16 tid, u16 *ssn) 3396 struct ieee80211_sta *sta, u16 tid, u16 *ssn)
3691{ 3397{
3692 struct iwl_priv *priv = hw->priv; 3398 struct iwl_priv *priv = hw->priv;
3693 int ret = -EINVAL; 3399 int ret = -EINVAL;
@@ -3768,10 +3474,10 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
3768 return ret; 3474 return ret;
3769} 3475}
3770 3476
3771static void iwl_mac_sta_notify(struct ieee80211_hw *hw, 3477static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
3772 struct ieee80211_vif *vif, 3478 struct ieee80211_vif *vif,
3773 enum sta_notify_cmd cmd, 3479 enum sta_notify_cmd cmd,
3774 struct ieee80211_sta *sta) 3480 struct ieee80211_sta *sta)
3775{ 3481{
3776 struct iwl_priv *priv = hw->priv; 3482 struct iwl_priv *priv = hw->priv;
3777 struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; 3483 struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
@@ -3798,9 +3504,9 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
3798 } 3504 }
3799} 3505}
3800 3506
3801static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, 3507int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
3802 struct ieee80211_vif *vif, 3508 struct ieee80211_vif *vif,
3803 struct ieee80211_sta *sta) 3509 struct ieee80211_sta *sta)
3804{ 3510{
3805 struct iwl_priv *priv = hw->priv; 3511 struct iwl_priv *priv = hw->priv;
3806 struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; 3512 struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
@@ -3841,8 +3547,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
3841 return 0; 3547 return 0;
3842} 3548}
3843 3549
3844static void iwl_mac_channel_switch(struct ieee80211_hw *hw, 3550void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
3845 struct ieee80211_channel_switch *ch_switch) 3551 struct ieee80211_channel_switch *ch_switch)
3846{ 3552{
3847 struct iwl_priv *priv = hw->priv; 3553 struct iwl_priv *priv = hw->priv;
3848 const struct iwl_channel_info *ch_info; 3554 const struct iwl_channel_info *ch_info;
@@ -3939,10 +3645,10 @@ out_exit:
3939 IWL_DEBUG_MAC80211(priv, "leave\n"); 3645 IWL_DEBUG_MAC80211(priv, "leave\n");
3940} 3646}
3941 3647
3942static void iwlagn_configure_filter(struct ieee80211_hw *hw, 3648void iwlagn_configure_filter(struct ieee80211_hw *hw,
3943 unsigned int changed_flags, 3649 unsigned int changed_flags,
3944 unsigned int *total_flags, 3650 unsigned int *total_flags,
3945 u64 multicast) 3651 u64 multicast)
3946{ 3652{
3947 struct iwl_priv *priv = hw->priv; 3653 struct iwl_priv *priv = hw->priv;
3948 __le32 filter_or = 0, filter_nand = 0; 3654 __le32 filter_or = 0, filter_nand = 0;
@@ -3988,7 +3694,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
3988 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; 3694 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
3989} 3695}
3990 3696
3991static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop) 3697void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
3992{ 3698{
3993 struct iwl_priv *priv = hw->priv; 3699 struct iwl_priv *priv = hw->priv;
3994 3700
@@ -4198,25 +3904,24 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
4198} 3904}
4199 3905
4200struct ieee80211_ops iwlagn_hw_ops = { 3906struct ieee80211_ops iwlagn_hw_ops = {
4201 .tx = iwl_mac_tx, 3907 .tx = iwlagn_mac_tx,
4202 .start = iwl_mac_start, 3908 .start = iwlagn_mac_start,
4203 .stop = iwl_mac_stop, 3909 .stop = iwlagn_mac_stop,
4204 .add_interface = iwl_mac_add_interface, 3910 .add_interface = iwl_mac_add_interface,
4205 .remove_interface = iwl_mac_remove_interface, 3911 .remove_interface = iwl_mac_remove_interface,
4206 .config = iwl_mac_config, 3912 .config = iwlagn_mac_config,
4207 .configure_filter = iwlagn_configure_filter, 3913 .configure_filter = iwlagn_configure_filter,
4208 .set_key = iwl_mac_set_key, 3914 .set_key = iwlagn_mac_set_key,
4209 .update_tkip_key = iwl_mac_update_tkip_key, 3915 .update_tkip_key = iwlagn_mac_update_tkip_key,
4210 .conf_tx = iwl_mac_conf_tx, 3916 .conf_tx = iwl_mac_conf_tx,
4211 .reset_tsf = iwl_mac_reset_tsf, 3917 .bss_info_changed = iwlagn_bss_info_changed,
4212 .bss_info_changed = iwl_bss_info_changed, 3918 .ampdu_action = iwlagn_mac_ampdu_action,
4213 .ampdu_action = iwl_mac_ampdu_action,
4214 .hw_scan = iwl_mac_hw_scan, 3919 .hw_scan = iwl_mac_hw_scan,
4215 .sta_notify = iwl_mac_sta_notify, 3920 .sta_notify = iwlagn_mac_sta_notify,
4216 .sta_add = iwlagn_mac_sta_add, 3921 .sta_add = iwlagn_mac_sta_add,
4217 .sta_remove = iwl_mac_sta_remove, 3922 .sta_remove = iwl_mac_sta_remove,
4218 .channel_switch = iwl_mac_channel_switch, 3923 .channel_switch = iwlagn_mac_channel_switch,
4219 .flush = iwl_mac_flush, 3924 .flush = iwlagn_mac_flush,
4220 .tx_last_beacon = iwl_mac_tx_last_beacon, 3925 .tx_last_beacon = iwl_mac_tx_last_beacon,
4221}; 3926};
4222 3927
@@ -4287,6 +3992,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
4287 dev_printk(KERN_DEBUG, &(pdev->dev), 3992 dev_printk(KERN_DEBUG, &(pdev->dev),
4288 "sw scan support is deprecated\n"); 3993 "sw scan support is deprecated\n");
4289 iwlagn_hw_ops.hw_scan = NULL; 3994 iwlagn_hw_ops.hw_scan = NULL;
3995#ifdef CONFIG_IWL4965
3996 iwl4965_hw_ops.hw_scan = NULL;
3997#endif
4290 } 3998 }
4291 3999
4292 hw = iwl_alloc_all(cfg); 4000 hw = iwl_alloc_all(cfg);
@@ -4321,6 +4029,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
4321 BIT(NL80211_IFTYPE_ADHOC); 4029 BIT(NL80211_IFTYPE_ADHOC);
4322 priv->contexts[IWL_RXON_CTX_BSS].interface_modes = 4030 priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
4323 BIT(NL80211_IFTYPE_STATION); 4031 BIT(NL80211_IFTYPE_STATION);
4032 priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
4324 priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS; 4033 priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
4325 priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS; 4034 priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
4326 priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS; 4035 priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index ba88e78e6116..aca93f4477a8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -103,6 +103,7 @@ extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
103extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; 103extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
104 104
105extern struct ieee80211_ops iwlagn_hw_ops; 105extern struct ieee80211_ops iwlagn_hw_ops;
106extern struct ieee80211_ops iwl4965_hw_ops;
106 107
107int iwl_reset_ict(struct iwl_priv *priv); 108int iwl_reset_ict(struct iwl_priv *priv);
108void iwl_disable_ict(struct iwl_priv *priv); 109void iwl_disable_ict(struct iwl_priv *priv);
@@ -134,6 +135,11 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
134/* RXON */ 135/* RXON */
135int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); 136int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
136void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); 137void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
138int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed);
139void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
140 struct ieee80211_vif *vif,
141 struct ieee80211_bss_conf *bss_conf,
142 u32 changes);
137 143
138/* uCode */ 144/* uCode */
139int iwlagn_load_ucode(struct iwl_priv *priv); 145int iwlagn_load_ucode(struct iwl_priv *priv);
@@ -251,6 +257,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
251int iwlagn_send_rxon_assoc(struct iwl_priv *priv, 257int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
252 struct iwl_rxon_context *ctx); 258 struct iwl_rxon_context *ctx);
253int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); 259int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
260int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
254 261
255/* bt coex */ 262/* bt coex */
256void iwlagn_send_advance_bt_config(struct iwl_priv *priv); 263void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
@@ -320,4 +327,31 @@ void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
320int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); 327int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
321void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); 328void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
322 329
330/* mac80211 handlers (for 4965) */
331int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
332int iwlagn_mac_start(struct ieee80211_hw *hw);
333void iwlagn_mac_stop(struct ieee80211_hw *hw);
334void iwlagn_configure_filter(struct ieee80211_hw *hw,
335 unsigned int changed_flags,
336 unsigned int *total_flags,
337 u64 multicast);
338int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
339 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
340 struct ieee80211_key_conf *key);
341void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
342 struct ieee80211_vif *vif,
343 struct ieee80211_key_conf *keyconf,
344 struct ieee80211_sta *sta,
345 u32 iv32, u16 *phase1key);
346int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
347 struct ieee80211_vif *vif,
348 enum ieee80211_ampdu_mlme_action action,
349 struct ieee80211_sta *sta, u16 tid, u16 *ssn);
350int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
351 struct ieee80211_vif *vif,
352 struct ieee80211_sta *sta);
353void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
354 struct ieee80211_channel_switch *ch_switch);
355void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop);
356
323#endif /* __iwl_agn_h__ */ 357#endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index c93368083e1a..776713c6a7ff 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -100,35 +100,6 @@ out:
100} 100}
101EXPORT_SYMBOL(iwl_alloc_all); 101EXPORT_SYMBOL(iwl_alloc_all);
102 102
103/*
104 * QoS support
105*/
106static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
107{
108 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
109 return;
110
111 if (!ctx->is_active)
112 return;
113
114 ctx->qos_data.def_qos_parm.qos_flags = 0;
115
116 if (ctx->qos_data.qos_active)
117 ctx->qos_data.def_qos_parm.qos_flags |=
118 QOS_PARAM_FLG_UPDATE_EDCA_MSK;
119
120 if (ctx->ht.enabled)
121 ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
122
123 IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
124 ctx->qos_data.qos_active,
125 ctx->qos_data.def_qos_parm.qos_flags);
126
127 iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
128 sizeof(struct iwl_qosparam_cmd),
129 &ctx->qos_data.def_qos_parm, NULL);
130}
131
132#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ 103#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
133#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ 104#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
134static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, 105static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
@@ -1456,310 +1427,6 @@ int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
1456} 1427}
1457EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon); 1428EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
1458 1429
1459static void iwl_ht_conf(struct iwl_priv *priv,
1460 struct ieee80211_vif *vif)
1461{
1462 struct iwl_ht_config *ht_conf = &priv->current_ht_config;
1463 struct ieee80211_sta *sta;
1464 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
1465 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
1466
1467 IWL_DEBUG_MAC80211(priv, "enter:\n");
1468
1469 if (!ctx->ht.enabled)
1470 return;
1471
1472 ctx->ht.protection =
1473 bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
1474 ctx->ht.non_gf_sta_present =
1475 !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
1476
1477 ht_conf->single_chain_sufficient = false;
1478
1479 switch (vif->type) {
1480 case NL80211_IFTYPE_STATION:
1481 rcu_read_lock();
1482 sta = ieee80211_find_sta(vif, bss_conf->bssid);
1483 if (sta) {
1484 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
1485 int maxstreams;
1486
1487 maxstreams = (ht_cap->mcs.tx_params &
1488 IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
1489 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
1490 maxstreams += 1;
1491
1492 if ((ht_cap->mcs.rx_mask[1] == 0) &&
1493 (ht_cap->mcs.rx_mask[2] == 0))
1494 ht_conf->single_chain_sufficient = true;
1495 if (maxstreams <= 1)
1496 ht_conf->single_chain_sufficient = true;
1497 } else {
1498 /*
1499 * If at all, this can only happen through a race
1500 * when the AP disconnects us while we're still
1501 * setting up the connection, in that case mac80211
1502 * will soon tell us about that.
1503 */
1504 ht_conf->single_chain_sufficient = true;
1505 }
1506 rcu_read_unlock();
1507 break;
1508 case NL80211_IFTYPE_ADHOC:
1509 ht_conf->single_chain_sufficient = true;
1510 break;
1511 default:
1512 break;
1513 }
1514
1515 IWL_DEBUG_MAC80211(priv, "leave\n");
1516}
1517
1518static inline void iwl_set_no_assoc(struct iwl_priv *priv,
1519 struct ieee80211_vif *vif)
1520{
1521 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
1522
1523 iwl_led_disassociate(priv);
1524 /*
1525 * inform the ucode that there is no longer an
1526 * association and that no more packets should be
1527 * sent
1528 */
1529 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
1530 ctx->staging.assoc_id = 0;
1531 iwlcore_commit_rxon(priv, ctx);
1532}
1533
1534static void iwlcore_beacon_update(struct ieee80211_hw *hw,
1535 struct ieee80211_vif *vif)
1536{
1537 struct iwl_priv *priv = hw->priv;
1538 unsigned long flags;
1539 __le64 timestamp;
1540 struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
1541
1542 if (!skb)
1543 return;
1544
1545 IWL_DEBUG_ASSOC(priv, "enter\n");
1546
1547 lockdep_assert_held(&priv->mutex);
1548
1549 if (!priv->beacon_ctx) {
1550 IWL_ERR(priv, "update beacon but no beacon context!\n");
1551 dev_kfree_skb(skb);
1552 return;
1553 }
1554
1555 spin_lock_irqsave(&priv->lock, flags);
1556
1557 if (priv->beacon_skb)
1558 dev_kfree_skb(priv->beacon_skb);
1559
1560 priv->beacon_skb = skb;
1561
1562 timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
1563 priv->timestamp = le64_to_cpu(timestamp);
1564
1565 IWL_DEBUG_ASSOC(priv, "leave\n");
1566
1567 spin_unlock_irqrestore(&priv->lock, flags);
1568
1569 if (!iwl_is_ready_rf(priv)) {
1570 IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
1571 return;
1572 }
1573
1574 priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif);
1575}
1576
1577void iwl_bss_info_changed(struct ieee80211_hw *hw,
1578 struct ieee80211_vif *vif,
1579 struct ieee80211_bss_conf *bss_conf,
1580 u32 changes)
1581{
1582 struct iwl_priv *priv = hw->priv;
1583 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
1584 int ret;
1585
1586 IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
1587
1588 if (!iwl_is_alive(priv))
1589 return;
1590
1591 mutex_lock(&priv->mutex);
1592
1593 if (changes & (BSS_CHANGED_BSSID | BSS_CHANGED_ASSOC |
1594 BSS_CHANGED_BEACON_ENABLED)) {
1595 /*
1596 * If there is currently a HW scan going on in the
1597 * background then we need to cancel it else the RXON
1598 * below in post_associate or set_no_assoc can fail.
1599 */
1600 if (iwl_scan_cancel_timeout(priv, 200)) {
1601 IWL_WARN(priv, "Can not cancel scan\n");
1602 goto out;
1603 }
1604 }
1605
1606 if (changes & BSS_CHANGED_QOS) {
1607 unsigned long flags;
1608
1609 spin_lock_irqsave(&priv->lock, flags);
1610 ctx->qos_data.qos_active = bss_conf->qos;
1611 iwl_update_qos(priv, ctx);
1612 spin_unlock_irqrestore(&priv->lock, flags);
1613 }
1614
1615 if (changes & BSS_CHANGED_BEACON_ENABLED) {
1616 /*
1617 * the add_interface code must make sure we only ever
1618 * have a single interface that could be beaconing at
1619 * any time.
1620 */
1621 if (vif->bss_conf.enable_beacon)
1622 priv->beacon_ctx = ctx;
1623 else
1624 priv->beacon_ctx = NULL;
1625 }
1626
1627 if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
1628 dev_kfree_skb(priv->beacon_skb);
1629 priv->beacon_skb = ieee80211_beacon_get(hw, vif);
1630 }
1631
1632 if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
1633 iwl_send_rxon_timing(priv, ctx);
1634
1635 if (changes & BSS_CHANGED_BSSID) {
1636 IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
1637
1638 /* mac80211 only sets assoc when in STATION mode */
1639 if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
1640 memcpy(ctx->staging.bssid_addr,
1641 bss_conf->bssid, ETH_ALEN);
1642
1643 /* currently needed in a few places */
1644 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
1645 } else {
1646 ctx->staging.filter_flags &=
1647 ~RXON_FILTER_ASSOC_MSK;
1648 }
1649
1650 }
1651
1652 /*
1653 * This needs to be after setting the BSSID in case
1654 * mac80211 decides to do both changes at once because
1655 * it will invoke post_associate.
1656 */
1657 if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
1658 iwlcore_beacon_update(hw, vif);
1659
1660 if (changes & BSS_CHANGED_ERP_PREAMBLE) {
1661 IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
1662 bss_conf->use_short_preamble);
1663 if (bss_conf->use_short_preamble)
1664 ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
1665 else
1666 ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
1667 }
1668
1669 if (changes & BSS_CHANGED_ERP_CTS_PROT) {
1670 IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
1671 if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
1672 ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
1673 else
1674 ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
1675 if (bss_conf->use_cts_prot)
1676 ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
1677 else
1678 ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
1679 }
1680
1681 if (changes & BSS_CHANGED_BASIC_RATES) {
1682 /* XXX use this information
1683 *
1684 * To do that, remove code from iwl_set_rate() and put something
1685 * like this here:
1686 *
1687 if (A-band)
1688 ctx->staging.ofdm_basic_rates =
1689 bss_conf->basic_rates;
1690 else
1691 ctx->staging.ofdm_basic_rates =
1692 bss_conf->basic_rates >> 4;
1693 ctx->staging.cck_basic_rates =
1694 bss_conf->basic_rates & 0xF;
1695 */
1696 }
1697
1698 if (changes & BSS_CHANGED_HT) {
1699 iwl_ht_conf(priv, vif);
1700
1701 if (priv->cfg->ops->hcmd->set_rxon_chain)
1702 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
1703 }
1704
1705 if (changes & BSS_CHANGED_ASSOC) {
1706 IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
1707 if (bss_conf->assoc) {
1708 priv->timestamp = bss_conf->timestamp;
1709
1710 iwl_led_associate(priv);
1711
1712 if (!iwl_is_rfkill(priv))
1713 priv->cfg->ops->lib->post_associate(priv, vif);
1714 } else
1715 iwl_set_no_assoc(priv, vif);
1716 }
1717
1718 if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
1719 IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
1720 changes);
1721 ret = iwl_send_rxon_assoc(priv, ctx);
1722 if (!ret) {
1723 /* Sync active_rxon with latest change. */
1724 memcpy((void *)&ctx->active,
1725 &ctx->staging,
1726 sizeof(struct iwl_rxon_cmd));
1727 }
1728 }
1729
1730 if (changes & BSS_CHANGED_BEACON_ENABLED) {
1731 if (vif->bss_conf.enable_beacon) {
1732 memcpy(ctx->staging.bssid_addr,
1733 bss_conf->bssid, ETH_ALEN);
1734 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
1735 iwl_led_associate(priv);
1736 iwlcore_config_ap(priv, vif);
1737 } else
1738 iwl_set_no_assoc(priv, vif);
1739 }
1740
1741 if (changes & BSS_CHANGED_IBSS) {
1742 ret = priv->cfg->ops->lib->manage_ibss_station(priv, vif,
1743 bss_conf->ibss_joined);
1744 if (ret)
1745 IWL_ERR(priv, "failed to %s IBSS station %pM\n",
1746 bss_conf->ibss_joined ? "add" : "remove",
1747 bss_conf->bssid);
1748 }
1749
1750 if (changes & BSS_CHANGED_IDLE &&
1751 priv->cfg->ops->hcmd->set_pan_params) {
1752 if (priv->cfg->ops->hcmd->set_pan_params(priv))
1753 IWL_ERR(priv, "failed to update PAN params\n");
1754 }
1755
1756out:
1757 mutex_unlock(&priv->mutex);
1758
1759 IWL_DEBUG_MAC80211(priv, "leave\n");
1760}
1761EXPORT_SYMBOL(iwl_bss_info_changed);
1762
1763static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) 1430static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
1764{ 1431{
1765 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); 1432 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
@@ -1899,204 +1566,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
1899} 1566}
1900EXPORT_SYMBOL(iwl_mac_remove_interface); 1567EXPORT_SYMBOL(iwl_mac_remove_interface);
1901 1568
1902/**
1903 * iwl_mac_config - mac80211 config callback
1904 */
1905int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
1906{
1907 struct iwl_priv *priv = hw->priv;
1908 const struct iwl_channel_info *ch_info;
1909 struct ieee80211_conf *conf = &hw->conf;
1910 struct ieee80211_channel *channel = conf->channel;
1911 struct iwl_ht_config *ht_conf = &priv->current_ht_config;
1912 struct iwl_rxon_context *ctx;
1913 unsigned long flags = 0;
1914 int ret = 0;
1915 u16 ch;
1916 int scan_active = 0;
1917
1918 mutex_lock(&priv->mutex);
1919
1920 IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
1921 channel->hw_value, changed);
1922
1923 if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
1924 test_bit(STATUS_SCANNING, &priv->status))) {
1925 scan_active = 1;
1926 IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
1927 }
1928
1929 if (changed & (IEEE80211_CONF_CHANGE_SMPS |
1930 IEEE80211_CONF_CHANGE_CHANNEL)) {
1931 /* mac80211 uses static for non-HT which is what we want */
1932 priv->current_ht_config.smps = conf->smps_mode;
1933
1934 /*
1935 * Recalculate chain counts.
1936 *
1937 * If monitor mode is enabled then mac80211 will
1938 * set up the SM PS mode to OFF if an HT channel is
1939 * configured.
1940 */
1941 if (priv->cfg->ops->hcmd->set_rxon_chain)
1942 for_each_context(priv, ctx)
1943 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
1944 }
1945
1946 /* during scanning mac80211 will delay channel setting until
1947 * scan finish with changed = 0
1948 */
1949 if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
1950 if (scan_active)
1951 goto set_ch_out;
1952
1953 ch = channel->hw_value;
1954 ch_info = iwl_get_channel_info(priv, channel->band, ch);
1955 if (!is_channel_valid(ch_info)) {
1956 IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
1957 ret = -EINVAL;
1958 goto set_ch_out;
1959 }
1960
1961 spin_lock_irqsave(&priv->lock, flags);
1962
1963 for_each_context(priv, ctx) {
1964 /* Configure HT40 channels */
1965 ctx->ht.enabled = conf_is_ht(conf);
1966 if (ctx->ht.enabled) {
1967 if (conf_is_ht40_minus(conf)) {
1968 ctx->ht.extension_chan_offset =
1969 IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1970 ctx->ht.is_40mhz = true;
1971 } else if (conf_is_ht40_plus(conf)) {
1972 ctx->ht.extension_chan_offset =
1973 IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1974 ctx->ht.is_40mhz = true;
1975 } else {
1976 ctx->ht.extension_chan_offset =
1977 IEEE80211_HT_PARAM_CHA_SEC_NONE;
1978 ctx->ht.is_40mhz = false;
1979 }
1980 } else
1981 ctx->ht.is_40mhz = false;
1982
1983 /*
1984 * Default to no protection. Protection mode will
1985 * later be set from BSS config in iwl_ht_conf
1986 */
1987 ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
1988
1989 /* if we are switching from ht to 2.4 clear flags
1990 * from any ht related info since 2.4 does not
1991 * support ht */
1992 if ((le16_to_cpu(ctx->staging.channel) != ch))
1993 ctx->staging.flags = 0;
1994
1995 iwl_set_rxon_channel(priv, channel, ctx);
1996 iwl_set_rxon_ht(priv, ht_conf);
1997
1998 iwl_set_flags_for_band(priv, ctx, channel->band,
1999 ctx->vif);
2000 }
2001
2002 spin_unlock_irqrestore(&priv->lock, flags);
2003
2004 if (priv->cfg->ops->lib->update_bcast_stations)
2005 ret = priv->cfg->ops->lib->update_bcast_stations(priv);
2006
2007 set_ch_out:
2008 /* The list of supported rates and rate mask can be different
2009 * for each band; since the band may have changed, reset
2010 * the rate mask to what mac80211 lists */
2011 iwl_set_rate(priv);
2012 }
2013
2014 if (changed & (IEEE80211_CONF_CHANGE_PS |
2015 IEEE80211_CONF_CHANGE_IDLE)) {
2016 ret = iwl_power_update_mode(priv, false);
2017 if (ret)
2018 IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
2019 }
2020
2021 if (changed & IEEE80211_CONF_CHANGE_POWER) {
2022 IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
2023 priv->tx_power_user_lmt, conf->power_level);
2024
2025 ret = iwl_set_tx_power(priv, conf->power_level, false);
2026 if (ret)
2027 IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
2028 }
2029
2030 if (!iwl_is_ready(priv)) {
2031 IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
2032 goto out;
2033 }
2034
2035 if (scan_active)
2036 goto out;
2037
2038 for_each_context(priv, ctx) {
2039 if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
2040 iwlcore_commit_rxon(priv, ctx);
2041 else
2042 IWL_DEBUG_INFO(priv,
2043 "Not re-sending same RXON configuration.\n");
2044 }
2045
2046out:
2047 IWL_DEBUG_MAC80211(priv, "leave\n");
2048 mutex_unlock(&priv->mutex);
2049 return ret;
2050}
2051EXPORT_SYMBOL(iwl_mac_config);
2052
2053void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
2054{
2055 struct iwl_priv *priv = hw->priv;
2056 unsigned long flags;
2057 /* IBSS can only be the IWL_RXON_CTX_BSS context */
2058 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
2059
2060 mutex_lock(&priv->mutex);
2061 IWL_DEBUG_MAC80211(priv, "enter\n");
2062
2063 spin_lock_irqsave(&priv->lock, flags);
2064 memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
2065 spin_unlock_irqrestore(&priv->lock, flags);
2066
2067 spin_lock_irqsave(&priv->lock, flags);
2068
2069 /* new association get rid of ibss beacon skb */
2070 if (priv->beacon_skb)
2071 dev_kfree_skb(priv->beacon_skb);
2072
2073 priv->beacon_skb = NULL;
2074
2075 priv->timestamp = 0;
2076
2077 spin_unlock_irqrestore(&priv->lock, flags);
2078
2079 iwl_scan_cancel_timeout(priv, 100);
2080 if (!iwl_is_ready_rf(priv)) {
2081 IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
2082 mutex_unlock(&priv->mutex);
2083 return;
2084 }
2085
2086 /* we are restarting association process
2087 * clear RXON_FILTER_ASSOC_MSK bit
2088 */
2089 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2090 iwlcore_commit_rxon(priv, ctx);
2091
2092 iwl_set_rate(priv);
2093
2094 mutex_unlock(&priv->mutex);
2095
2096 IWL_DEBUG_MAC80211(priv, "leave\n");
2097}
2098EXPORT_SYMBOL(iwl_mac_reset_tsf);
2099
2100int iwl_alloc_txq_mem(struct iwl_priv *priv) 1569int iwl_alloc_txq_mem(struct iwl_priv *priv)
2101{ 1570{
2102 if (!priv->txq) 1571 if (!priv->txq)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 917d42eae55a..854613e4f2be 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -193,9 +193,6 @@ struct iwl_lib_ops {
193 /* power */ 193 /* power */
194 int (*send_tx_power) (struct iwl_priv *priv); 194 int (*send_tx_power) (struct iwl_priv *priv);
195 void (*update_chain_flags)(struct iwl_priv *priv); 195 void (*update_chain_flags)(struct iwl_priv *priv);
196 void (*post_associate)(struct iwl_priv *priv,
197 struct ieee80211_vif *vif);
198 void (*config_ap)(struct iwl_priv *priv, struct ieee80211_vif *vif);
199 irqreturn_t (*isr) (int irq, void *data); 196 irqreturn_t (*isr) (int irq, void *data);
200 197
201 /* eeprom operations (as defined in iwl-eeprom.h) */ 198 /* eeprom operations (as defined in iwl-eeprom.h) */
@@ -203,10 +200,6 @@ struct iwl_lib_ops {
203 200
204 /* temperature */ 201 /* temperature */
205 struct iwl_temp_ops temp_ops; 202 struct iwl_temp_ops temp_ops;
206 /* station management */
207 int (*manage_ibss_station)(struct iwl_priv *priv,
208 struct ieee80211_vif *vif, bool add);
209 int (*update_bcast_stations)(struct iwl_priv *priv);
210 /* recover from tx queue stall */ 203 /* recover from tx queue stall */
211 void (*recover_from_tx_stall)(unsigned long data); 204 void (*recover_from_tx_stall)(unsigned long data);
212 /* check for plcp health */ 205 /* check for plcp health */
@@ -235,12 +228,22 @@ struct iwl_nic_ops {
235 void (*additional_nic_config)(struct iwl_priv *priv); 228 void (*additional_nic_config)(struct iwl_priv *priv);
236}; 229};
237 230
231struct iwl_legacy_ops {
232 void (*post_associate)(struct iwl_priv *priv);
233 void (*config_ap)(struct iwl_priv *priv);
234 /* station management */
235 int (*update_bcast_stations)(struct iwl_priv *priv);
236 int (*manage_ibss_station)(struct iwl_priv *priv,
237 struct ieee80211_vif *vif, bool add);
238};
239
238struct iwl_ops { 240struct iwl_ops {
239 const struct iwl_lib_ops *lib; 241 const struct iwl_lib_ops *lib;
240 const struct iwl_hcmd_ops *hcmd; 242 const struct iwl_hcmd_ops *hcmd;
241 const struct iwl_hcmd_utils_ops *utils; 243 const struct iwl_hcmd_utils_ops *utils;
242 const struct iwl_led_ops *led; 244 const struct iwl_led_ops *led;
243 const struct iwl_nic_ops *nic; 245 const struct iwl_nic_ops *nic;
246 const struct iwl_legacy_ops *legacy;
244 const struct ieee80211_ops *ieee80211_ops; 247 const struct ieee80211_ops *ieee80211_ops;
245}; 248};
246 249
@@ -425,18 +428,10 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
425 u32 decrypt_res, 428 u32 decrypt_res,
426 struct ieee80211_rx_status *stats); 429 struct ieee80211_rx_status *stats);
427void iwl_irq_handle_error(struct iwl_priv *priv); 430void iwl_irq_handle_error(struct iwl_priv *priv);
428void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif);
429void iwl_bss_info_changed(struct ieee80211_hw *hw,
430 struct ieee80211_vif *vif,
431 struct ieee80211_bss_conf *bss_conf,
432 u32 changes);
433int iwl_mac_add_interface(struct ieee80211_hw *hw, 431int iwl_mac_add_interface(struct ieee80211_hw *hw,
434 struct ieee80211_vif *vif); 432 struct ieee80211_vif *vif);
435void iwl_mac_remove_interface(struct ieee80211_hw *hw, 433void iwl_mac_remove_interface(struct ieee80211_hw *hw,
436 struct ieee80211_vif *vif); 434 struct ieee80211_vif *vif);
437int iwl_mac_config(struct ieee80211_hw *hw, u32 changed);
438void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif);
439void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
440int iwl_alloc_txq_mem(struct iwl_priv *priv); 435int iwl_alloc_txq_mem(struct iwl_priv *priv);
441void iwl_free_txq_mem(struct iwl_priv *priv); 436void iwl_free_txq_mem(struct iwl_priv *priv);
442void iwlcore_tx_cmd_protection(struct iwl_priv *priv, 437void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
@@ -732,11 +727,6 @@ static inline int iwlcore_commit_rxon(struct iwl_priv *priv,
732{ 727{
733 return priv->cfg->ops->hcmd->commit_rxon(priv, ctx); 728 return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
734} 729}
735static inline void iwlcore_config_ap(struct iwl_priv *priv,
736 struct ieee80211_vif *vif)
737{
738 priv->cfg->ops->lib->config_ap(priv, vif);
739}
740static inline const struct ieee80211_supported_band *iwl_get_hw_mode( 730static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
741 struct iwl_priv *priv, enum ieee80211_band band) 731 struct iwl_priv *priv, enum ieee80211_band band)
742{ 732{
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index cd6daed99931..9fcaaf0cfe93 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1162,6 +1162,8 @@ struct iwl_rxon_context {
1162 */ 1162 */
1163 bool always_active, is_active; 1163 bool always_active, is_active;
1164 1164
1165 bool ht_need_multiple_chains;
1166
1165 enum iwl_rxon_context_id ctxid; 1167 enum iwl_rxon_context_id ctxid;
1166 1168
1167 u32 interface_modes, exclusive_interface_modes; 1169 u32 interface_modes, exclusive_interface_modes;
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 86c2b6fed0c6..5a9129219c90 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -134,6 +134,7 @@ int iwl_led_associate(struct iwl_priv *priv)
134 134
135 return 0; 135 return 0;
136} 136}
137EXPORT_SYMBOL(iwl_led_associate);
137 138
138int iwl_led_disassociate(struct iwl_priv *priv) 139int iwl_led_disassociate(struct iwl_priv *priv)
139{ 140{
@@ -141,6 +142,7 @@ int iwl_led_disassociate(struct iwl_priv *priv)
141 142
142 return 0; 143 return 0;
143} 144}
145EXPORT_SYMBOL(iwl_led_disassociate);
144 146
145/* 147/*
146 * calculate blink rate according to last second Tx/Rx activities 148 * calculate blink rate according to last second Tx/Rx activities
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.c b/drivers/net/wireless/iwlwifi/iwl-legacy.c
new file mode 100644
index 000000000000..b735fef9ee4b
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-legacy.c
@@ -0,0 +1,560 @@
1/******************************************************************************
2 *
3 * GPL LICENSE SUMMARY
4 *
5 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
19 * USA
20 *
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * Contact Information:
25 * Intel Linux Wireless <ilw@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *****************************************************************************/
28
29#include <linux/kernel.h>
30#include <net/mac80211.h>
31
32#include "iwl-dev.h"
33#include "iwl-core.h"
34#include "iwl-legacy.h"
35
36/**
37 * iwl_legacy_mac_config - mac80211 config callback
38 */
39int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
40{
41 struct iwl_priv *priv = hw->priv;
42 const struct iwl_channel_info *ch_info;
43 struct ieee80211_conf *conf = &hw->conf;
44 struct ieee80211_channel *channel = conf->channel;
45 struct iwl_ht_config *ht_conf = &priv->current_ht_config;
46 struct iwl_rxon_context *ctx;
47 unsigned long flags = 0;
48 int ret = 0;
49 u16 ch;
50 int scan_active = 0;
51
52 if (WARN_ON(!priv->cfg->ops->legacy))
53 return -EOPNOTSUPP;
54
55 mutex_lock(&priv->mutex);
56
57 IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
58 channel->hw_value, changed);
59
60 if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
61 test_bit(STATUS_SCANNING, &priv->status))) {
62 scan_active = 1;
63 IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
64 }
65
66 if (changed & (IEEE80211_CONF_CHANGE_SMPS |
67 IEEE80211_CONF_CHANGE_CHANNEL)) {
68 /* mac80211 uses static for non-HT which is what we want */
69 priv->current_ht_config.smps = conf->smps_mode;
70
71 /*
72 * Recalculate chain counts.
73 *
74 * If monitor mode is enabled then mac80211 will
75 * set up the SM PS mode to OFF if an HT channel is
76 * configured.
77 */
78 if (priv->cfg->ops->hcmd->set_rxon_chain)
79 for_each_context(priv, ctx)
80 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
81 }
82
83 /* during scanning mac80211 will delay channel setting until
84 * scan finish with changed = 0
85 */
86 if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
87 if (scan_active)
88 goto set_ch_out;
89
90 ch = channel->hw_value;
91 ch_info = iwl_get_channel_info(priv, channel->band, ch);
92 if (!is_channel_valid(ch_info)) {
93 IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
94 ret = -EINVAL;
95 goto set_ch_out;
96 }
97
98 spin_lock_irqsave(&priv->lock, flags);
99
100 for_each_context(priv, ctx) {
101 /* Configure HT40 channels */
102 ctx->ht.enabled = conf_is_ht(conf);
103 if (ctx->ht.enabled) {
104 if (conf_is_ht40_minus(conf)) {
105 ctx->ht.extension_chan_offset =
106 IEEE80211_HT_PARAM_CHA_SEC_BELOW;
107 ctx->ht.is_40mhz = true;
108 } else if (conf_is_ht40_plus(conf)) {
109 ctx->ht.extension_chan_offset =
110 IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
111 ctx->ht.is_40mhz = true;
112 } else {
113 ctx->ht.extension_chan_offset =
114 IEEE80211_HT_PARAM_CHA_SEC_NONE;
115 ctx->ht.is_40mhz = false;
116 }
117 } else
118 ctx->ht.is_40mhz = false;
119
120 /*
121 * Default to no protection. Protection mode will
122 * later be set from BSS config in iwl_ht_conf
123 */
124 ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
125
126 /* if we are switching from ht to 2.4 clear flags
127 * from any ht related info since 2.4 does not
128 * support ht */
129 if ((le16_to_cpu(ctx->staging.channel) != ch))
130 ctx->staging.flags = 0;
131
132 iwl_set_rxon_channel(priv, channel, ctx);
133 iwl_set_rxon_ht(priv, ht_conf);
134
135 iwl_set_flags_for_band(priv, ctx, channel->band,
136 ctx->vif);
137 }
138
139 spin_unlock_irqrestore(&priv->lock, flags);
140
141 if (priv->cfg->ops->legacy->update_bcast_stations)
142 ret = priv->cfg->ops->legacy->update_bcast_stations(priv);
143
144 set_ch_out:
145 /* The list of supported rates and rate mask can be different
146 * for each band; since the band may have changed, reset
147 * the rate mask to what mac80211 lists */
148 iwl_set_rate(priv);
149 }
150
151 if (changed & (IEEE80211_CONF_CHANGE_PS |
152 IEEE80211_CONF_CHANGE_IDLE)) {
153 ret = iwl_power_update_mode(priv, false);
154 if (ret)
155 IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
156 }
157
158 if (changed & IEEE80211_CONF_CHANGE_POWER) {
159 IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
160 priv->tx_power_user_lmt, conf->power_level);
161
162 iwl_set_tx_power(priv, conf->power_level, false);
163 }
164
165 if (!iwl_is_ready(priv)) {
166 IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
167 goto out;
168 }
169
170 if (scan_active)
171 goto out;
172
173 for_each_context(priv, ctx) {
174 if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
175 iwlcore_commit_rxon(priv, ctx);
176 else
177 IWL_DEBUG_INFO(priv,
178 "Not re-sending same RXON configuration.\n");
179 }
180
181out:
182 IWL_DEBUG_MAC80211(priv, "leave\n");
183 mutex_unlock(&priv->mutex);
184 return ret;
185}
186EXPORT_SYMBOL(iwl_legacy_mac_config);
187
188void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
189{
190 struct iwl_priv *priv = hw->priv;
191 unsigned long flags;
192 /* IBSS can only be the IWL_RXON_CTX_BSS context */
193 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
194
195 if (WARN_ON(!priv->cfg->ops->legacy))
196 return;
197
198 mutex_lock(&priv->mutex);
199 IWL_DEBUG_MAC80211(priv, "enter\n");
200
201 spin_lock_irqsave(&priv->lock, flags);
202 memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
203 spin_unlock_irqrestore(&priv->lock, flags);
204
205 spin_lock_irqsave(&priv->lock, flags);
206
207 /* new association get rid of ibss beacon skb */
208 if (priv->beacon_skb)
209 dev_kfree_skb(priv->beacon_skb);
210
211 priv->beacon_skb = NULL;
212
213 priv->timestamp = 0;
214
215 spin_unlock_irqrestore(&priv->lock, flags);
216
217 iwl_scan_cancel_timeout(priv, 100);
218 if (!iwl_is_ready_rf(priv)) {
219 IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
220 mutex_unlock(&priv->mutex);
221 return;
222 }
223
224 /* we are restarting association process
225 * clear RXON_FILTER_ASSOC_MSK bit
226 */
227 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
228 iwlcore_commit_rxon(priv, ctx);
229
230 iwl_set_rate(priv);
231
232 mutex_unlock(&priv->mutex);
233
234 IWL_DEBUG_MAC80211(priv, "leave\n");
235}
236EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
237
238static void iwl_ht_conf(struct iwl_priv *priv,
239 struct ieee80211_vif *vif)
240{
241 struct iwl_ht_config *ht_conf = &priv->current_ht_config;
242 struct ieee80211_sta *sta;
243 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
244 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
245
246 IWL_DEBUG_ASSOC(priv, "enter:\n");
247
248 if (!ctx->ht.enabled)
249 return;
250
251 ctx->ht.protection =
252 bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
253 ctx->ht.non_gf_sta_present =
254 !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
255
256 ht_conf->single_chain_sufficient = false;
257
258 switch (vif->type) {
259 case NL80211_IFTYPE_STATION:
260 rcu_read_lock();
261 sta = ieee80211_find_sta(vif, bss_conf->bssid);
262 if (sta) {
263 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
264 int maxstreams;
265
266 maxstreams = (ht_cap->mcs.tx_params &
267 IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
268 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
269 maxstreams += 1;
270
271 if ((ht_cap->mcs.rx_mask[1] == 0) &&
272 (ht_cap->mcs.rx_mask[2] == 0))
273 ht_conf->single_chain_sufficient = true;
274 if (maxstreams <= 1)
275 ht_conf->single_chain_sufficient = true;
276 } else {
277 /*
278 * If at all, this can only happen through a race
279 * when the AP disconnects us while we're still
280 * setting up the connection, in that case mac80211
281 * will soon tell us about that.
282 */
283 ht_conf->single_chain_sufficient = true;
284 }
285 rcu_read_unlock();
286 break;
287 case NL80211_IFTYPE_ADHOC:
288 ht_conf->single_chain_sufficient = true;
289 break;
290 default:
291 break;
292 }
293
294 IWL_DEBUG_ASSOC(priv, "leave\n");
295}
296
297static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
298{
299 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
300 return;
301
302 if (!ctx->is_active)
303 return;
304
305 ctx->qos_data.def_qos_parm.qos_flags = 0;
306
307 if (ctx->qos_data.qos_active)
308 ctx->qos_data.def_qos_parm.qos_flags |=
309 QOS_PARAM_FLG_UPDATE_EDCA_MSK;
310
311 if (ctx->ht.enabled)
312 ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
313
314 IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
315 ctx->qos_data.qos_active,
316 ctx->qos_data.def_qos_parm.qos_flags);
317
318 iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
319 sizeof(struct iwl_qosparam_cmd),
320 &ctx->qos_data.def_qos_parm, NULL);
321}
322
323static inline void iwl_set_no_assoc(struct iwl_priv *priv,
324 struct ieee80211_vif *vif)
325{
326 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
327
328 iwl_led_disassociate(priv);
329 /*
330 * inform the ucode that there is no longer an
331 * association and that no more packets should be
332 * sent
333 */
334 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
335 ctx->staging.assoc_id = 0;
336 iwlcore_commit_rxon(priv, ctx);
337}
338
339static void iwlcore_beacon_update(struct ieee80211_hw *hw,
340 struct ieee80211_vif *vif)
341{
342 struct iwl_priv *priv = hw->priv;
343 unsigned long flags;
344 __le64 timestamp;
345 struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
346
347 if (!skb)
348 return;
349
350 IWL_DEBUG_MAC80211(priv, "enter\n");
351
352 lockdep_assert_held(&priv->mutex);
353
354 if (!priv->beacon_ctx) {
355 IWL_ERR(priv, "update beacon but no beacon context!\n");
356 dev_kfree_skb(skb);
357 return;
358 }
359
360 spin_lock_irqsave(&priv->lock, flags);
361
362 if (priv->beacon_skb)
363 dev_kfree_skb(priv->beacon_skb);
364
365 priv->beacon_skb = skb;
366
367 timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
368 priv->timestamp = le64_to_cpu(timestamp);
369
370 IWL_DEBUG_MAC80211(priv, "leave\n");
371 spin_unlock_irqrestore(&priv->lock, flags);
372
373 if (!iwl_is_ready_rf(priv)) {
374 IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
375 return;
376 }
377
378 priv->cfg->ops->legacy->post_associate(priv);
379}
380
381void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
382 struct ieee80211_vif *vif,
383 struct ieee80211_bss_conf *bss_conf,
384 u32 changes)
385{
386 struct iwl_priv *priv = hw->priv;
387 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
388 int ret;
389
390 if (WARN_ON(!priv->cfg->ops->legacy))
391 return;
392
393 IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
394
395 if (!iwl_is_alive(priv))
396 return;
397
398 mutex_lock(&priv->mutex);
399
400 if (changes & BSS_CHANGED_QOS) {
401 unsigned long flags;
402
403 spin_lock_irqsave(&priv->lock, flags);
404 ctx->qos_data.qos_active = bss_conf->qos;
405 iwl_update_qos(priv, ctx);
406 spin_unlock_irqrestore(&priv->lock, flags);
407 }
408
409 if (changes & BSS_CHANGED_BEACON_ENABLED) {
410 /*
411 * the add_interface code must make sure we only ever
412 * have a single interface that could be beaconing at
413 * any time.
414 */
415 if (vif->bss_conf.enable_beacon)
416 priv->beacon_ctx = ctx;
417 else
418 priv->beacon_ctx = NULL;
419 }
420
421 if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
422 dev_kfree_skb(priv->beacon_skb);
423 priv->beacon_skb = ieee80211_beacon_get(hw, vif);
424 }
425
426 if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
427 iwl_send_rxon_timing(priv, ctx);
428
429 if (changes & BSS_CHANGED_BSSID) {
430 IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
431
432 /*
433 * If there is currently a HW scan going on in the
434 * background then we need to cancel it else the RXON
435 * below/in post_associate will fail.
436 */
437 if (iwl_scan_cancel_timeout(priv, 100)) {
438 IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
439 IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
440 mutex_unlock(&priv->mutex);
441 return;
442 }
443
444 /* mac80211 only sets assoc when in STATION mode */
445 if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
446 memcpy(ctx->staging.bssid_addr,
447 bss_conf->bssid, ETH_ALEN);
448
449 /* currently needed in a few places */
450 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
451 } else {
452 ctx->staging.filter_flags &=
453 ~RXON_FILTER_ASSOC_MSK;
454 }
455
456 }
457
458 /*
459 * This needs to be after setting the BSSID in case
460 * mac80211 decides to do both changes at once because
461 * it will invoke post_associate.
462 */
463 if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
464 iwlcore_beacon_update(hw, vif);
465
466 if (changes & BSS_CHANGED_ERP_PREAMBLE) {
467 IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
468 bss_conf->use_short_preamble);
469 if (bss_conf->use_short_preamble)
470 ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
471 else
472 ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
473 }
474
475 if (changes & BSS_CHANGED_ERP_CTS_PROT) {
476 IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
477 if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
478 ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
479 else
480 ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
481 if (bss_conf->use_cts_prot)
482 ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
483 else
484 ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
485 }
486
487 if (changes & BSS_CHANGED_BASIC_RATES) {
488 /* XXX use this information
489 *
490 * To do that, remove code from iwl_set_rate() and put something
491 * like this here:
492 *
493 if (A-band)
494 ctx->staging.ofdm_basic_rates =
495 bss_conf->basic_rates;
496 else
497 ctx->staging.ofdm_basic_rates =
498 bss_conf->basic_rates >> 4;
499 ctx->staging.cck_basic_rates =
500 bss_conf->basic_rates & 0xF;
501 */
502 }
503
504 if (changes & BSS_CHANGED_HT) {
505 iwl_ht_conf(priv, vif);
506
507 if (priv->cfg->ops->hcmd->set_rxon_chain)
508 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
509 }
510
511 if (changes & BSS_CHANGED_ASSOC) {
512 IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
513 if (bss_conf->assoc) {
514 priv->timestamp = bss_conf->timestamp;
515
516 iwl_led_associate(priv);
517
518 if (!iwl_is_rfkill(priv))
519 priv->cfg->ops->legacy->post_associate(priv);
520 } else
521 iwl_set_no_assoc(priv, vif);
522 }
523
524 if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
525 IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
526 changes);
527 ret = iwl_send_rxon_assoc(priv, ctx);
528 if (!ret) {
529 /* Sync active_rxon with latest change. */
530 memcpy((void *)&ctx->active,
531 &ctx->staging,
532 sizeof(struct iwl_rxon_cmd));
533 }
534 }
535
536 if (changes & BSS_CHANGED_BEACON_ENABLED) {
537 if (vif->bss_conf.enable_beacon) {
538 memcpy(ctx->staging.bssid_addr,
539 bss_conf->bssid, ETH_ALEN);
540 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
541 iwl_led_associate(priv);
542 priv->cfg->ops->legacy->config_ap(priv);
543 } else
544 iwl_set_no_assoc(priv, vif);
545 }
546
547 if (changes & BSS_CHANGED_IBSS) {
548 ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
549 bss_conf->ibss_joined);
550 if (ret)
551 IWL_ERR(priv, "failed to %s IBSS station %pM\n",
552 bss_conf->ibss_joined ? "add" : "remove",
553 bss_conf->bssid);
554 }
555
556 mutex_unlock(&priv->mutex);
557
558 IWL_DEBUG_MAC80211(priv, "leave\n");
559}
560EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.h b/drivers/net/wireless/iwlwifi/iwl-legacy.h
new file mode 100644
index 000000000000..2a746cbc30fe
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-legacy.h
@@ -0,0 +1,74 @@
1/******************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22 * USA
23 *
24 * The full GNU General Public License is included in this distribution
25 * in the file called LICENSE.GPL.
26 *
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 *
31 * BSD LICENSE
32 *
33 * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
45 * distribution.
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *****************************************************************************/
62
63#ifndef __iwl_legacy_h__
64#define __iwl_legacy_h__
65
66/* mac80211 handlers */
67int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
68void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
69void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
70 struct ieee80211_vif *vif,
71 struct ieee80211_bss_conf *bss_conf,
72 u32 changes);
73
74#endif /* __iwl_legacy_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index d42bb22e5ed5..73f2f3fcb49c 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -61,6 +61,7 @@
61#include "iwl-helpers.h" 61#include "iwl-helpers.h"
62#include "iwl-dev.h" 62#include "iwl-dev.h"
63#include "iwl-spectrum.h" 63#include "iwl-spectrum.h"
64#include "iwl-legacy.h"
64 65
65/* 66/*
66 * module name, copyright, version, etc. 67 * module name, copyright, version, etc.
@@ -3057,22 +3058,22 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
3057 mutex_unlock(&priv->mutex); 3058 mutex_unlock(&priv->mutex);
3058} 3059}
3059 3060
3060void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) 3061void iwl3945_post_associate(struct iwl_priv *priv)
3061{ 3062{
3062 int rc = 0; 3063 int rc = 0;
3063 struct ieee80211_conf *conf = NULL; 3064 struct ieee80211_conf *conf = NULL;
3064 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; 3065 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
3065 3066
3066 if (!vif || !priv->is_open) 3067 if (!ctx->vif || !priv->is_open)
3067 return; 3068 return;
3068 3069
3069 if (vif->type == NL80211_IFTYPE_AP) { 3070 if (ctx->vif->type == NL80211_IFTYPE_AP) {
3070 IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); 3071 IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
3071 return; 3072 return;
3072 } 3073 }
3073 3074
3074 IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", 3075 IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
3075 vif->bss_conf.aid, ctx->active.bssid_addr); 3076 ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
3076 3077
3077 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3078 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3078 return; 3079 return;
@@ -3091,18 +3092,18 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
3091 3092
3092 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; 3093 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
3093 3094
3094 ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); 3095 ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
3095 3096
3096 IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", 3097 IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
3097 vif->bss_conf.aid, vif->bss_conf.beacon_int); 3098 ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
3098 3099
3099 if (vif->bss_conf.use_short_preamble) 3100 if (ctx->vif->bss_conf.use_short_preamble)
3100 ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; 3101 ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
3101 else 3102 else
3102 ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; 3103 ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
3103 3104
3104 if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { 3105 if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
3105 if (vif->bss_conf.use_short_slot) 3106 if (ctx->vif->bss_conf.use_short_slot)
3106 ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; 3107 ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
3107 else 3108 else
3108 ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; 3109 ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
@@ -3110,7 +3111,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
3110 3111
3111 iwl3945_commit_rxon(priv, ctx); 3112 iwl3945_commit_rxon(priv, ctx);
3112 3113
3113 switch (vif->type) { 3114 switch (ctx->vif->type) {
3114 case NL80211_IFTYPE_STATION: 3115 case NL80211_IFTYPE_STATION:
3115 iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); 3116 iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
3116 break; 3117 break;
@@ -3119,7 +3120,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
3119 break; 3120 break;
3120 default: 3121 default:
3121 IWL_ERR(priv, "%s Should not be called in %d mode\n", 3122 IWL_ERR(priv, "%s Should not be called in %d mode\n",
3122 __func__, vif->type); 3123 __func__, ctx->vif->type);
3123 break; 3124 break;
3124 } 3125 }
3125} 3126}
@@ -3234,9 +3235,10 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
3234 return NETDEV_TX_OK; 3235 return NETDEV_TX_OK;
3235} 3236}
3236 3237
3237void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) 3238void iwl3945_config_ap(struct iwl_priv *priv)
3238{ 3239{
3239 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; 3240 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
3241 struct ieee80211_vif *vif = ctx->vif;
3240 int rc = 0; 3242 int rc = 0;
3241 3243
3242 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3244 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -3830,12 +3832,12 @@ struct ieee80211_ops iwl3945_hw_ops = {
3830 .stop = iwl3945_mac_stop, 3832 .stop = iwl3945_mac_stop,
3831 .add_interface = iwl_mac_add_interface, 3833 .add_interface = iwl_mac_add_interface,
3832 .remove_interface = iwl_mac_remove_interface, 3834 .remove_interface = iwl_mac_remove_interface,
3833 .config = iwl_mac_config, 3835 .config = iwl_legacy_mac_config,
3834 .configure_filter = iwl3945_configure_filter, 3836 .configure_filter = iwl3945_configure_filter,
3835 .set_key = iwl3945_mac_set_key, 3837 .set_key = iwl3945_mac_set_key,
3836 .conf_tx = iwl_mac_conf_tx, 3838 .conf_tx = iwl_mac_conf_tx,
3837 .reset_tsf = iwl_mac_reset_tsf, 3839 .reset_tsf = iwl_legacy_mac_reset_tsf,
3838 .bss_info_changed = iwl_bss_info_changed, 3840 .bss_info_changed = iwl_legacy_mac_bss_info_changed,
3839 .hw_scan = iwl_mac_hw_scan, 3841 .hw_scan = iwl_mac_hw_scan,
3840 .sta_add = iwl3945_mac_sta_add, 3842 .sta_add = iwl3945_mac_sta_add,
3841 .sta_remove = iwl_mac_sta_remove, 3843 .sta_remove = iwl_mac_sta_remove,