diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-1000.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 318 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 562 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 385 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 34 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 531 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 30 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-led.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-legacy.c | 560 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-legacy.h | 74 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 30 |
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 | |||
2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o | 2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o |
3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o | 3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o |
4 | iwlcore-objs += iwl-scan.o iwl-led.o | 4 | iwlcore-objs += iwl-scan.o iwl-led.o |
5 | iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o | ||
6 | iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o | ||
5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 7 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
6 | iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 8 | iwlcore-$(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 | |||
16 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o | 18 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o |
17 | 19 | ||
18 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 20 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
21 | iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o | ||
19 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o | 22 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o |
20 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o | 23 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o |
21 | iwlagn-$(CONFIG_IWL5000) += iwl-1000.o | 24 | iwlagn-$(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 | ||
2740 | static 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 | |||
2743 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | 2746 | static 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); |
265 | extern void iwl3945_disable_events(struct iwl_priv *priv); | 265 | extern void iwl3945_disable_events(struct iwl_priv *priv); |
266 | extern int iwl4965_get_temperature(const struct iwl_priv *priv); | 266 | extern int iwl4965_get_temperature(const struct iwl_priv *priv); |
267 | extern void iwl3945_post_associate(struct iwl_priv *priv, | 267 | extern void iwl3945_post_associate(struct iwl_priv *priv); |
268 | struct ieee80211_vif *vif); | 268 | extern void iwl3945_config_ap(struct iwl_priv *priv); |
269 | extern void iwl3945_config_ap(struct iwl_priv *priv, | ||
270 | struct ieee80211_vif *vif); | ||
271 | 269 | ||
272 | extern int iwl3945_commit_rxon(struct iwl_priv *priv, | 270 | extern 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 | ||
52 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | 53 | static int iwl4965_send_tx_power(struct iwl_priv *priv); |
53 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | 54 | static 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 | ||
1447 | static 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 | |||
1446 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, | 1583 | static 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 | ||
2213 | static struct iwl_hcmd_ops iwl4965_hcmd = { | 2350 | static 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 | ||
2369 | static 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 | |||
2451 | static 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 | |||
2232 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | 2512 | static 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 | ||
2579 | static 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 | |||
2586 | struct 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 | |||
2303 | static const struct iwl_ops iwl4965_ops = { | 2608 | static 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 | ||
2311 | static struct iwl_base_params iwl4965_base_params = { | 2617 | static 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 | |||
33 | static 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 | |||
51 | static 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 | */ | ||
83 | int 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 | |||
253 | int 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 | |||
382 | static 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 | |||
410 | static 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 | |||
478 | void 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"); | |||
90 | static int iwlagn_ant_coupling; | 90 | static int iwlagn_ant_coupling; |
91 | static bool iwlagn_bt_ch_announce = 1; | 91 | static 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 | */ | ||
101 | int 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 | |||
240 | void iwl_update_chain_flags(struct iwl_priv *priv) | 93 | void 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 | } |
397 | static int iwl_send_beacon_cmd(struct iwl_priv *priv) | 250 | |
251 | int 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 | |||
3297 | void 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 | ||
3460 | static int iwl_mac_start(struct ieee80211_hw *hw) | 3228 | int 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 | ||
3501 | static void iwl_mac_stop(struct ieee80211_hw *hw) | 3269 | void 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 | ||
3523 | static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 3291 | int 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 | ||
3539 | void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | 3307 | void 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 | |||
3599 | static 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 | ||
3617 | static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 3324 | int 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 | ||
3687 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | 3393 | int 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 | ||
3771 | static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | 3477 | static 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 | ||
3801 | static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | 3507 | int 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 | ||
3844 | static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | 3550 | void 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 | ||
3942 | static void iwlagn_configure_filter(struct ieee80211_hw *hw, | 3648 | void 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 | ||
3991 | static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop) | 3697 | void 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 | ||
4200 | struct ieee80211_ops iwlagn_hw_ops = { | 3906 | struct 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; | |||
103 | extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; | 103 | extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; |
104 | 104 | ||
105 | extern struct ieee80211_ops iwlagn_hw_ops; | 105 | extern struct ieee80211_ops iwlagn_hw_ops; |
106 | extern struct ieee80211_ops iwl4965_hw_ops; | ||
106 | 107 | ||
107 | int iwl_reset_ict(struct iwl_priv *priv); | 108 | int iwl_reset_ict(struct iwl_priv *priv); |
108 | void iwl_disable_ict(struct iwl_priv *priv); | 109 | void 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 */ |
135 | int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | 136 | int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); |
136 | void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | 137 | void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); |
138 | int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed); | ||
139 | void 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 */ |
139 | int iwlagn_load_ucode(struct iwl_priv *priv); | 145 | int iwlagn_load_ucode(struct iwl_priv *priv); |
@@ -251,6 +257,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
251 | int iwlagn_send_rxon_assoc(struct iwl_priv *priv, | 257 | int iwlagn_send_rxon_assoc(struct iwl_priv *priv, |
252 | struct iwl_rxon_context *ctx); | 258 | struct iwl_rxon_context *ctx); |
253 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); | 259 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); |
260 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); | ||
254 | 261 | ||
255 | /* bt coex */ | 262 | /* bt coex */ |
256 | void iwlagn_send_advance_bt_config(struct iwl_priv *priv); | 263 | void 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); | |||
320 | int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); | 327 | int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); |
321 | void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); | 328 | void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); |
322 | 329 | ||
330 | /* mac80211 handlers (for 4965) */ | ||
331 | int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
332 | int iwlagn_mac_start(struct ieee80211_hw *hw); | ||
333 | void iwlagn_mac_stop(struct ieee80211_hw *hw); | ||
334 | void iwlagn_configure_filter(struct ieee80211_hw *hw, | ||
335 | unsigned int changed_flags, | ||
336 | unsigned int *total_flags, | ||
337 | u64 multicast); | ||
338 | int 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); | ||
341 | void 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); | ||
346 | int 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); | ||
350 | int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | ||
351 | struct ieee80211_vif *vif, | ||
352 | struct ieee80211_sta *sta); | ||
353 | void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | ||
354 | struct ieee80211_channel_switch *ch_switch); | ||
355 | void 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 | } |
101 | EXPORT_SYMBOL(iwl_alloc_all); | 101 | EXPORT_SYMBOL(iwl_alloc_all); |
102 | 102 | ||
103 | /* | ||
104 | * QoS support | ||
105 | */ | ||
106 | static 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 */ |
134 | static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | 105 | static 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 | } |
1457 | EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon); | 1428 | EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon); |
1458 | 1429 | ||
1459 | static 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 | |||
1518 | static 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 | |||
1534 | static 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 | |||
1577 | void 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 | |||
1756 | out: | ||
1757 | mutex_unlock(&priv->mutex); | ||
1758 | |||
1759 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
1760 | } | ||
1761 | EXPORT_SYMBOL(iwl_bss_info_changed); | ||
1762 | |||
1763 | static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) | 1430 | static 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 | } |
1900 | EXPORT_SYMBOL(iwl_mac_remove_interface); | 1567 | EXPORT_SYMBOL(iwl_mac_remove_interface); |
1901 | 1568 | ||
1902 | /** | ||
1903 | * iwl_mac_config - mac80211 config callback | ||
1904 | */ | ||
1905 | int 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 | |||
2046 | out: | ||
2047 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2048 | mutex_unlock(&priv->mutex); | ||
2049 | return ret; | ||
2050 | } | ||
2051 | EXPORT_SYMBOL(iwl_mac_config); | ||
2052 | |||
2053 | void 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 | } | ||
2098 | EXPORT_SYMBOL(iwl_mac_reset_tsf); | ||
2099 | |||
2100 | int iwl_alloc_txq_mem(struct iwl_priv *priv) | 1569 | int 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 | ||
231 | struct 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 | |||
238 | struct iwl_ops { | 240 | struct 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); |
427 | void iwl_irq_handle_error(struct iwl_priv *priv); | 430 | void iwl_irq_handle_error(struct iwl_priv *priv); |
428 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); | ||
429 | void iwl_bss_info_changed(struct ieee80211_hw *hw, | ||
430 | struct ieee80211_vif *vif, | ||
431 | struct ieee80211_bss_conf *bss_conf, | ||
432 | u32 changes); | ||
433 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 431 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
434 | struct ieee80211_vif *vif); | 432 | struct ieee80211_vif *vif); |
435 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 433 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
436 | struct ieee80211_vif *vif); | 434 | struct ieee80211_vif *vif); |
437 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); | ||
438 | void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif); | ||
439 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); | ||
440 | int iwl_alloc_txq_mem(struct iwl_priv *priv); | 435 | int iwl_alloc_txq_mem(struct iwl_priv *priv); |
441 | void iwl_free_txq_mem(struct iwl_priv *priv); | 436 | void iwl_free_txq_mem(struct iwl_priv *priv); |
442 | void iwlcore_tx_cmd_protection(struct iwl_priv *priv, | 437 | void 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 | } |
735 | static 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 | } | ||
740 | static inline const struct ieee80211_supported_band *iwl_get_hw_mode( | 730 | static 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 | } |
137 | EXPORT_SYMBOL(iwl_led_associate); | ||
137 | 138 | ||
138 | int iwl_led_disassociate(struct iwl_priv *priv) | 139 | int 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 | } |
145 | EXPORT_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 | */ | ||
39 | int 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 | |||
181 | out: | ||
182 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
183 | mutex_unlock(&priv->mutex); | ||
184 | return ret; | ||
185 | } | ||
186 | EXPORT_SYMBOL(iwl_legacy_mac_config); | ||
187 | |||
188 | void 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 | } | ||
236 | EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf); | ||
237 | |||
238 | static 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 | |||
297 | static 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 | |||
323 | static 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 | |||
339 | static 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 | |||
381 | void 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 | } | ||
560 | EXPORT_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 */ | ||
67 | int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed); | ||
68 | void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw); | ||
69 | void 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 | ||
3060 | void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | 3061 | void 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 | ||
3237 | void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | 3238 | void 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, |