diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-20 20:43:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-20 20:43:29 -0400 |
commit | db6d8c7a4027b48d797b369a53f8470aaeed7063 (patch) | |
tree | e140c104a89abc2154e1f41a7db8ebecbb6fa0b4 /drivers/net/wireless/iwlwifi/iwl3945-base.c | |
parent | 3a533374283aea50eab3976d8a6d30532175f009 (diff) | |
parent | fb65a7c091529bfffb1262515252c0d0f6241c5c (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (1232 commits)
iucv: Fix bad merging.
net_sched: Add size table for qdiscs
net_sched: Add accessor function for packet length for qdiscs
net_sched: Add qdisc_enqueue wrapper
highmem: Export totalhigh_pages.
ipv6 mcast: Omit redundant address family checks in ip6_mc_source().
net: Use standard structures for generic socket address structures.
ipv6 netns: Make several "global" sysctl variables namespace aware.
netns: Use net_eq() to compare net-namespaces for optimization.
ipv6: remove unused macros from net/ipv6.h
ipv6: remove unused parameter from ip6_ra_control
tcp: fix kernel panic with listening_get_next
tcp: Remove redundant checks when setting eff_sacks
tcp: options clean up
tcp: Fix MD5 signatures for non-linear skbs
sctp: Update sctp global memory limit allocations.
sctp: remove unnecessary byteshifting, calculate directly in big-endian
sctp: Allow only 1 listening socket with SO_REUSEADDR
sctp: Do not leak memory on multiple listen() calls
sctp: Support ipv6only AF_INET6 sockets.
...
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 535 |
1 files changed, 263 insertions, 272 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6027e1119c3f..4a22d3fba75b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -102,16 +102,6 @@ MODULE_VERSION(DRV_VERSION); | |||
102 | MODULE_AUTHOR(DRV_COPYRIGHT); | 102 | MODULE_AUTHOR(DRV_COPYRIGHT); |
103 | MODULE_LICENSE("GPL"); | 103 | MODULE_LICENSE("GPL"); |
104 | 104 | ||
105 | static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr) | ||
106 | { | ||
107 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
108 | int hdr_len = ieee80211_get_hdrlen(fc); | ||
109 | |||
110 | if ((fc & 0x00cc) == (IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA)) | ||
111 | return (__le16 *) ((u8 *) hdr + hdr_len - QOS_CONTROL_LEN); | ||
112 | return NULL; | ||
113 | } | ||
114 | |||
115 | static const struct ieee80211_supported_band *iwl3945_get_band( | 105 | static const struct ieee80211_supported_band *iwl3945_get_band( |
116 | struct iwl3945_priv *priv, enum ieee80211_band band) | 106 | struct iwl3945_priv *priv, enum ieee80211_band band) |
117 | { | 107 | { |
@@ -547,10 +537,20 @@ static inline int iwl3945_is_init(struct iwl3945_priv *priv) | |||
547 | return test_bit(STATUS_INIT, &priv->status); | 537 | return test_bit(STATUS_INIT, &priv->status); |
548 | } | 538 | } |
549 | 539 | ||
540 | static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv) | ||
541 | { | ||
542 | return test_bit(STATUS_RF_KILL_SW, &priv->status); | ||
543 | } | ||
544 | |||
545 | static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv) | ||
546 | { | ||
547 | return test_bit(STATUS_RF_KILL_HW, &priv->status); | ||
548 | } | ||
549 | |||
550 | static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) | 550 | static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) |
551 | { | 551 | { |
552 | return test_bit(STATUS_RF_KILL_HW, &priv->status) || | 552 | return iwl3945_is_rfkill_hw(priv) || |
553 | test_bit(STATUS_RF_KILL_SW, &priv->status); | 553 | iwl3945_is_rfkill_sw(priv); |
554 | } | 554 | } |
555 | 555 | ||
556 | static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) | 556 | static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) |
@@ -980,7 +980,7 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv) | |||
980 | { | 980 | { |
981 | 981 | ||
982 | /* These items are only settable from the full RXON command */ | 982 | /* These items are only settable from the full RXON command */ |
983 | if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) || | 983 | if (!(iwl3945_is_associated(priv)) || |
984 | compare_ether_addr(priv->staging_rxon.bssid_addr, | 984 | compare_ether_addr(priv->staging_rxon.bssid_addr, |
985 | priv->active_rxon.bssid_addr) || | 985 | priv->active_rxon.bssid_addr) || |
986 | compare_ether_addr(priv->staging_rxon.node_addr, | 986 | compare_ether_addr(priv->staging_rxon.node_addr, |
@@ -2035,36 +2035,6 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode) | |||
2035 | return rc; | 2035 | return rc; |
2036 | } | 2036 | } |
2037 | 2037 | ||
2038 | int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) | ||
2039 | { | ||
2040 | /* Filter incoming packets to determine if they are targeted toward | ||
2041 | * this network, discarding packets coming from ourselves */ | ||
2042 | switch (priv->iw_mode) { | ||
2043 | case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ | ||
2044 | /* packets from our adapter are dropped (echo) */ | ||
2045 | if (!compare_ether_addr(header->addr2, priv->mac_addr)) | ||
2046 | return 0; | ||
2047 | /* {broad,multi}cast packets to our IBSS go through */ | ||
2048 | if (is_multicast_ether_addr(header->addr1)) | ||
2049 | return !compare_ether_addr(header->addr3, priv->bssid); | ||
2050 | /* packets to our adapter go through */ | ||
2051 | return !compare_ether_addr(header->addr1, priv->mac_addr); | ||
2052 | case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ | ||
2053 | /* packets from our adapter are dropped (echo) */ | ||
2054 | if (!compare_ether_addr(header->addr3, priv->mac_addr)) | ||
2055 | return 0; | ||
2056 | /* {broad,multi}cast packets to our BSS go through */ | ||
2057 | if (is_multicast_ether_addr(header->addr1)) | ||
2058 | return !compare_ether_addr(header->addr2, priv->bssid); | ||
2059 | /* packets to our adapter go through */ | ||
2060 | return !compare_ether_addr(header->addr1, priv->mac_addr); | ||
2061 | default: | ||
2062 | return 1; | ||
2063 | } | ||
2064 | |||
2065 | return 1; | ||
2066 | } | ||
2067 | |||
2068 | /** | 2038 | /** |
2069 | * iwl3945_scan_cancel - Cancel any currently executing HW scan | 2039 | * iwl3945_scan_cancel - Cancel any currently executing HW scan |
2070 | * | 2040 | * |
@@ -2117,20 +2087,6 @@ static int iwl3945_scan_cancel_timeout(struct iwl3945_priv *priv, unsigned long | |||
2117 | return ret; | 2087 | return ret; |
2118 | } | 2088 | } |
2119 | 2089 | ||
2120 | static void iwl3945_sequence_reset(struct iwl3945_priv *priv) | ||
2121 | { | ||
2122 | /* Reset ieee stats */ | ||
2123 | |||
2124 | /* We don't reset the net_device_stats (ieee->stats) on | ||
2125 | * re-association */ | ||
2126 | |||
2127 | priv->last_seq_num = -1; | ||
2128 | priv->last_frag_num = -1; | ||
2129 | priv->last_packet_time = 0; | ||
2130 | |||
2131 | iwl3945_scan_cancel(priv); | ||
2132 | } | ||
2133 | |||
2134 | #define MAX_UCODE_BEACON_INTERVAL 1024 | 2090 | #define MAX_UCODE_BEACON_INTERVAL 1024 |
2135 | #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) | 2091 | #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) |
2136 | 2092 | ||
@@ -2322,7 +2278,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) | |||
2322 | #endif | 2278 | #endif |
2323 | 2279 | ||
2324 | ch_info = iwl3945_get_channel_info(priv, priv->band, | 2280 | ch_info = iwl3945_get_channel_info(priv, priv->band, |
2325 | le16_to_cpu(priv->staging_rxon.channel)); | 2281 | le16_to_cpu(priv->active_rxon.channel)); |
2326 | 2282 | ||
2327 | if (!ch_info) | 2283 | if (!ch_info) |
2328 | ch_info = &priv->channel_info[0]; | 2284 | ch_info = &priv->channel_info[0]; |
@@ -2389,12 +2345,13 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) | |||
2389 | } | 2345 | } |
2390 | 2346 | ||
2391 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv, | 2347 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv, |
2392 | struct ieee80211_tx_control *ctl, | 2348 | struct ieee80211_tx_info *info, |
2393 | struct iwl3945_cmd *cmd, | 2349 | struct iwl3945_cmd *cmd, |
2394 | struct sk_buff *skb_frag, | 2350 | struct sk_buff *skb_frag, |
2395 | int last_frag) | 2351 | int last_frag) |
2396 | { | 2352 | { |
2397 | struct iwl3945_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo; | 2353 | struct iwl3945_hw_key *keyinfo = |
2354 | &priv->stations[info->control.hw_key->hw_key_idx].keyinfo; | ||
2398 | 2355 | ||
2399 | switch (keyinfo->alg) { | 2356 | switch (keyinfo->alg) { |
2400 | case ALG_CCMP: | 2357 | case ALG_CCMP: |
@@ -2417,7 +2374,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv, | |||
2417 | 2374 | ||
2418 | case ALG_WEP: | 2375 | case ALG_WEP: |
2419 | cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP | | 2376 | cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP | |
2420 | (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; | 2377 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; |
2421 | 2378 | ||
2422 | if (keyinfo->keylen == 13) | 2379 | if (keyinfo->keylen == 13) |
2423 | cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; | 2380 | cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; |
@@ -2425,7 +2382,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv, | |||
2425 | memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen); | 2382 | memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen); |
2426 | 2383 | ||
2427 | IWL_DEBUG_TX("Configuring packet for WEP encryption " | 2384 | IWL_DEBUG_TX("Configuring packet for WEP encryption " |
2428 | "with key %d\n", ctl->key_idx); | 2385 | "with key %d\n", info->control.hw_key->hw_key_idx); |
2429 | break; | 2386 | break; |
2430 | 2387 | ||
2431 | default: | 2388 | default: |
@@ -2439,20 +2396,19 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv, | |||
2439 | */ | 2396 | */ |
2440 | static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, | 2397 | static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, |
2441 | struct iwl3945_cmd *cmd, | 2398 | struct iwl3945_cmd *cmd, |
2442 | struct ieee80211_tx_control *ctrl, | 2399 | struct ieee80211_tx_info *info, |
2443 | struct ieee80211_hdr *hdr, | 2400 | struct ieee80211_hdr *hdr, |
2444 | int is_unicast, u8 std_id) | 2401 | int is_unicast, u8 std_id) |
2445 | { | 2402 | { |
2446 | __le16 *qc; | 2403 | __le16 fc = hdr->frame_control; |
2447 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
2448 | __le32 tx_flags = cmd->cmd.tx.tx_flags; | 2404 | __le32 tx_flags = cmd->cmd.tx.tx_flags; |
2449 | 2405 | ||
2450 | cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 2406 | cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
2451 | if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) { | 2407 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { |
2452 | tx_flags |= TX_CMD_FLG_ACK_MSK; | 2408 | tx_flags |= TX_CMD_FLG_ACK_MSK; |
2453 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) | 2409 | if (ieee80211_is_mgmt(fc)) |
2454 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 2410 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
2455 | if (ieee80211_is_probe_response(fc) && | 2411 | if (ieee80211_is_probe_resp(fc) && |
2456 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) | 2412 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) |
2457 | tx_flags |= TX_CMD_FLG_TSF_MSK; | 2413 | tx_flags |= TX_CMD_FLG_TSF_MSK; |
2458 | } else { | 2414 | } else { |
@@ -2461,20 +2417,21 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, | |||
2461 | } | 2417 | } |
2462 | 2418 | ||
2463 | cmd->cmd.tx.sta_id = std_id; | 2419 | cmd->cmd.tx.sta_id = std_id; |
2464 | if (ieee80211_get_morefrag(hdr)) | 2420 | if (ieee80211_has_morefrags(fc)) |
2465 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | 2421 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; |
2466 | 2422 | ||
2467 | qc = ieee80211_get_qos_ctrl(hdr); | 2423 | if (ieee80211_is_data_qos(fc)) { |
2468 | if (qc) { | 2424 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
2469 | cmd->cmd.tx.tid_tspec = (u8) (le16_to_cpu(*qc) & 0xf); | 2425 | cmd->cmd.tx.tid_tspec = qc[0] & 0xf; |
2470 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | 2426 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; |
2471 | } else | 2427 | } else { |
2472 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 2428 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
2429 | } | ||
2473 | 2430 | ||
2474 | if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) { | 2431 | if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { |
2475 | tx_flags |= TX_CMD_FLG_RTS_MSK; | 2432 | tx_flags |= TX_CMD_FLG_RTS_MSK; |
2476 | tx_flags &= ~TX_CMD_FLG_CTS_MSK; | 2433 | tx_flags &= ~TX_CMD_FLG_CTS_MSK; |
2477 | } else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { | 2434 | } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { |
2478 | tx_flags &= ~TX_CMD_FLG_RTS_MSK; | 2435 | tx_flags &= ~TX_CMD_FLG_RTS_MSK; |
2479 | tx_flags |= TX_CMD_FLG_CTS_MSK; | 2436 | tx_flags |= TX_CMD_FLG_CTS_MSK; |
2480 | } | 2437 | } |
@@ -2483,9 +2440,8 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, | |||
2483 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | 2440 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; |
2484 | 2441 | ||
2485 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | 2442 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); |
2486 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { | 2443 | if (ieee80211_is_mgmt(fc)) { |
2487 | if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ || | 2444 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) |
2488 | (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ) | ||
2489 | cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3); | 2445 | cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3); |
2490 | else | 2446 | else |
2491 | cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2); | 2447 | cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2); |
@@ -2549,6 +2505,11 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h | |||
2549 | iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); | 2505 | iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); |
2550 | return priv->hw_setting.bcast_sta_id; | 2506 | return priv->hw_setting.bcast_sta_id; |
2551 | } | 2507 | } |
2508 | /* If we are in monitor mode, use BCAST. This is required for | ||
2509 | * packet injection. */ | ||
2510 | case IEEE80211_IF_TYPE_MNTR: | ||
2511 | return priv->hw_setting.bcast_sta_id; | ||
2512 | |||
2552 | default: | 2513 | default: |
2553 | IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); | 2514 | IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); |
2554 | return priv->hw_setting.bcast_sta_id; | 2515 | return priv->hw_setting.bcast_sta_id; |
@@ -2558,25 +2519,27 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h | |||
2558 | /* | 2519 | /* |
2559 | * start REPLY_TX command process | 2520 | * start REPLY_TX command process |
2560 | */ | 2521 | */ |
2561 | static int iwl3945_tx_skb(struct iwl3945_priv *priv, | 2522 | static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) |
2562 | struct sk_buff *skb, struct ieee80211_tx_control *ctl) | ||
2563 | { | 2523 | { |
2564 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 2524 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
2525 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
2565 | struct iwl3945_tfd_frame *tfd; | 2526 | struct iwl3945_tfd_frame *tfd; |
2566 | u32 *control_flags; | 2527 | u32 *control_flags; |
2567 | int txq_id = ctl->queue; | 2528 | int txq_id = skb_get_queue_mapping(skb); |
2568 | struct iwl3945_tx_queue *txq = NULL; | 2529 | struct iwl3945_tx_queue *txq = NULL; |
2569 | struct iwl3945_queue *q = NULL; | 2530 | struct iwl3945_queue *q = NULL; |
2570 | dma_addr_t phys_addr; | 2531 | dma_addr_t phys_addr; |
2571 | dma_addr_t txcmd_phys; | 2532 | dma_addr_t txcmd_phys; |
2572 | struct iwl3945_cmd *out_cmd = NULL; | 2533 | struct iwl3945_cmd *out_cmd = NULL; |
2573 | u16 len, idx, len_org; | 2534 | u16 len, idx, len_org, hdr_len; |
2574 | u8 id, hdr_len, unicast; | 2535 | u8 id; |
2536 | u8 unicast; | ||
2575 | u8 sta_id; | 2537 | u8 sta_id; |
2538 | u8 tid = 0; | ||
2576 | u16 seq_number = 0; | 2539 | u16 seq_number = 0; |
2577 | u16 fc; | 2540 | __le16 fc; |
2578 | __le16 *qc; | ||
2579 | u8 wait_write_ptr = 0; | 2541 | u8 wait_write_ptr = 0; |
2542 | u8 *qc = NULL; | ||
2580 | unsigned long flags; | 2543 | unsigned long flags; |
2581 | int rc; | 2544 | int rc; |
2582 | 2545 | ||
@@ -2586,12 +2549,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2586 | goto drop_unlock; | 2549 | goto drop_unlock; |
2587 | } | 2550 | } |
2588 | 2551 | ||
2589 | if (!priv->vif) { | 2552 | if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) { |
2590 | IWL_DEBUG_DROP("Dropping - !priv->vif\n"); | ||
2591 | goto drop_unlock; | ||
2592 | } | ||
2593 | |||
2594 | if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) { | ||
2595 | IWL_ERROR("ERROR: No TX rate available.\n"); | 2553 | IWL_ERROR("ERROR: No TX rate available.\n"); |
2596 | goto drop_unlock; | 2554 | goto drop_unlock; |
2597 | } | 2555 | } |
@@ -2599,28 +2557,29 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2599 | unicast = !is_multicast_ether_addr(hdr->addr1); | 2557 | unicast = !is_multicast_ether_addr(hdr->addr1); |
2600 | id = 0; | 2558 | id = 0; |
2601 | 2559 | ||
2602 | fc = le16_to_cpu(hdr->frame_control); | 2560 | fc = hdr->frame_control; |
2603 | 2561 | ||
2604 | #ifdef CONFIG_IWL3945_DEBUG | 2562 | #ifdef CONFIG_IWL3945_DEBUG |
2605 | if (ieee80211_is_auth(fc)) | 2563 | if (ieee80211_is_auth(fc)) |
2606 | IWL_DEBUG_TX("Sending AUTH frame\n"); | 2564 | IWL_DEBUG_TX("Sending AUTH frame\n"); |
2607 | else if (ieee80211_is_assoc_request(fc)) | 2565 | else if (ieee80211_is_assoc_req(fc)) |
2608 | IWL_DEBUG_TX("Sending ASSOC frame\n"); | 2566 | IWL_DEBUG_TX("Sending ASSOC frame\n"); |
2609 | else if (ieee80211_is_reassoc_request(fc)) | 2567 | else if (ieee80211_is_reassoc_req(fc)) |
2610 | IWL_DEBUG_TX("Sending REASSOC frame\n"); | 2568 | IWL_DEBUG_TX("Sending REASSOC frame\n"); |
2611 | #endif | 2569 | #endif |
2612 | 2570 | ||
2613 | /* drop all data frame if we are not associated */ | 2571 | /* drop all data frame if we are not associated */ |
2614 | if ((!iwl3945_is_associated(priv) || | 2572 | if (ieee80211_is_data(fc) && |
2615 | ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id)) && | 2573 | (priv->iw_mode != IEEE80211_IF_TYPE_MNTR) && /* packet injection */ |
2616 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { | 2574 | (!iwl3945_is_associated(priv) || |
2575 | ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id))) { | ||
2617 | IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); | 2576 | IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); |
2618 | goto drop_unlock; | 2577 | goto drop_unlock; |
2619 | } | 2578 | } |
2620 | 2579 | ||
2621 | spin_unlock_irqrestore(&priv->lock, flags); | 2580 | spin_unlock_irqrestore(&priv->lock, flags); |
2622 | 2581 | ||
2623 | hdr_len = ieee80211_get_hdrlen(fc); | 2582 | hdr_len = ieee80211_get_hdrlen(le16_to_cpu(fc)); |
2624 | 2583 | ||
2625 | /* Find (or create) index into station table for destination station */ | 2584 | /* Find (or create) index into station table for destination station */ |
2626 | sta_id = iwl3945_get_sta_id(priv, hdr); | 2585 | sta_id = iwl3945_get_sta_id(priv, hdr); |
@@ -2634,9 +2593,9 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2634 | 2593 | ||
2635 | IWL_DEBUG_RATE("station Id %d\n", sta_id); | 2594 | IWL_DEBUG_RATE("station Id %d\n", sta_id); |
2636 | 2595 | ||
2637 | qc = ieee80211_get_qos_ctrl(hdr); | 2596 | if (ieee80211_is_data_qos(fc)) { |
2638 | if (qc) { | 2597 | qc = ieee80211_get_qos_ctl(hdr); |
2639 | u8 tid = (u8)(le16_to_cpu(*qc) & 0xf); | 2598 | tid = qc[0] & 0xf; |
2640 | seq_number = priv->stations[sta_id].tid[tid].seq_number & | 2599 | seq_number = priv->stations[sta_id].tid[tid].seq_number & |
2641 | IEEE80211_SCTL_SEQ; | 2600 | IEEE80211_SCTL_SEQ; |
2642 | hdr->seq_ctrl = cpu_to_le16(seq_number) | | 2601 | hdr->seq_ctrl = cpu_to_le16(seq_number) | |
@@ -2660,8 +2619,6 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2660 | /* Set up driver data for this TFD */ | 2619 | /* Set up driver data for this TFD */ |
2661 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl3945_tx_info)); | 2620 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl3945_tx_info)); |
2662 | txq->txb[q->write_ptr].skb[0] = skb; | 2621 | txq->txb[q->write_ptr].skb[0] = skb; |
2663 | memcpy(&(txq->txb[q->write_ptr].status.control), | ||
2664 | ctl, sizeof(struct ieee80211_tx_control)); | ||
2665 | 2622 | ||
2666 | /* Init first empty entry in queue's array of Tx/cmd buffers */ | 2623 | /* Init first empty entry in queue's array of Tx/cmd buffers */ |
2667 | out_cmd = &txq->cmd[idx]; | 2624 | out_cmd = &txq->cmd[idx]; |
@@ -2710,8 +2667,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2710 | * first entry */ | 2667 | * first entry */ |
2711 | iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); | 2668 | iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); |
2712 | 2669 | ||
2713 | if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) | 2670 | if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) |
2714 | iwl3945_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0); | 2671 | iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, 0); |
2715 | 2672 | ||
2716 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 2673 | /* Set up TFD's 2nd entry to point directly to remainder of skb, |
2717 | * if any (802.11 null frames have no payload). */ | 2674 | * if any (802.11 null frames have no payload). */ |
@@ -2736,18 +2693,17 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2736 | out_cmd->cmd.tx.len = cpu_to_le16(len); | 2693 | out_cmd->cmd.tx.len = cpu_to_le16(len); |
2737 | 2694 | ||
2738 | /* TODO need this for burst mode later on */ | 2695 | /* TODO need this for burst mode later on */ |
2739 | iwl3945_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id); | 2696 | iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, unicast, sta_id); |
2740 | 2697 | ||
2741 | /* set is_hcca to 0; it probably will never be implemented */ | 2698 | /* set is_hcca to 0; it probably will never be implemented */ |
2742 | iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0); | 2699 | iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0); |
2743 | 2700 | ||
2744 | out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; | 2701 | out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; |
2745 | out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; | 2702 | out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; |
2746 | 2703 | ||
2747 | if (!ieee80211_get_morefrag(hdr)) { | 2704 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
2748 | txq->need_update = 1; | 2705 | txq->need_update = 1; |
2749 | if (qc) { | 2706 | if (qc) { |
2750 | u8 tid = (u8)(le16_to_cpu(*qc) & 0xf); | ||
2751 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | 2707 | priv->stations[sta_id].tid[tid].seq_number = seq_number; |
2752 | } | 2708 | } |
2753 | } else { | 2709 | } else { |
@@ -2759,7 +2715,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2759 | sizeof(out_cmd->cmd.tx)); | 2715 | sizeof(out_cmd->cmd.tx)); |
2760 | 2716 | ||
2761 | iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, | 2717 | iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, |
2762 | ieee80211_get_hdrlen(fc)); | 2718 | ieee80211_get_hdrlen(le16_to_cpu(fc))); |
2763 | 2719 | ||
2764 | /* Tell device the write index *just past* this latest filled TFD */ | 2720 | /* Tell device the write index *just past* this latest filled TFD */ |
2765 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 2721 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
@@ -2778,7 +2734,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, | |||
2778 | spin_unlock_irqrestore(&priv->lock, flags); | 2734 | spin_unlock_irqrestore(&priv->lock, flags); |
2779 | } | 2735 | } |
2780 | 2736 | ||
2781 | ieee80211_stop_queue(priv->hw, ctl->queue); | 2737 | ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb)); |
2782 | } | 2738 | } |
2783 | 2739 | ||
2784 | return 0; | 2740 | return 0; |
@@ -2888,7 +2844,8 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio) | |||
2888 | return; | 2844 | return; |
2889 | } | 2845 | } |
2890 | 2846 | ||
2891 | queue_work(priv->workqueue, &priv->restart); | 2847 | if (priv->is_open) |
2848 | queue_work(priv->workqueue, &priv->restart); | ||
2892 | return; | 2849 | return; |
2893 | } | 2850 | } |
2894 | 2851 | ||
@@ -2924,72 +2881,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, | |||
2924 | } | 2881 | } |
2925 | } | 2882 | } |
2926 | 2883 | ||
2927 | #define IWL_PACKET_RETRY_TIME HZ | ||
2928 | |||
2929 | int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) | ||
2930 | { | ||
2931 | u16 sc = le16_to_cpu(header->seq_ctrl); | ||
2932 | u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4; | ||
2933 | u16 frag = sc & IEEE80211_SCTL_FRAG; | ||
2934 | u16 *last_seq, *last_frag; | ||
2935 | unsigned long *last_time; | ||
2936 | |||
2937 | switch (priv->iw_mode) { | ||
2938 | case IEEE80211_IF_TYPE_IBSS:{ | ||
2939 | struct list_head *p; | ||
2940 | struct iwl3945_ibss_seq *entry = NULL; | ||
2941 | u8 *mac = header->addr2; | ||
2942 | int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1); | ||
2943 | |||
2944 | __list_for_each(p, &priv->ibss_mac_hash[index]) { | ||
2945 | entry = list_entry(p, struct iwl3945_ibss_seq, list); | ||
2946 | if (!compare_ether_addr(entry->mac, mac)) | ||
2947 | break; | ||
2948 | } | ||
2949 | if (p == &priv->ibss_mac_hash[index]) { | ||
2950 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | ||
2951 | if (!entry) { | ||
2952 | IWL_ERROR("Cannot malloc new mac entry\n"); | ||
2953 | return 0; | ||
2954 | } | ||
2955 | memcpy(entry->mac, mac, ETH_ALEN); | ||
2956 | entry->seq_num = seq; | ||
2957 | entry->frag_num = frag; | ||
2958 | entry->packet_time = jiffies; | ||
2959 | list_add(&entry->list, &priv->ibss_mac_hash[index]); | ||
2960 | return 0; | ||
2961 | } | ||
2962 | last_seq = &entry->seq_num; | ||
2963 | last_frag = &entry->frag_num; | ||
2964 | last_time = &entry->packet_time; | ||
2965 | break; | ||
2966 | } | ||
2967 | case IEEE80211_IF_TYPE_STA: | ||
2968 | last_seq = &priv->last_seq_num; | ||
2969 | last_frag = &priv->last_frag_num; | ||
2970 | last_time = &priv->last_packet_time; | ||
2971 | break; | ||
2972 | default: | ||
2973 | return 0; | ||
2974 | } | ||
2975 | if ((*last_seq == seq) && | ||
2976 | time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) { | ||
2977 | if (*last_frag == frag) | ||
2978 | goto drop; | ||
2979 | if (*last_frag + 1 != frag) | ||
2980 | /* out-of-order fragment */ | ||
2981 | goto drop; | ||
2982 | } else | ||
2983 | *last_seq = seq; | ||
2984 | |||
2985 | *last_frag = frag; | ||
2986 | *last_time = jiffies; | ||
2987 | return 0; | ||
2988 | |||
2989 | drop: | ||
2990 | return 1; | ||
2991 | } | ||
2992 | |||
2993 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT | 2884 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT |
2994 | 2885 | ||
2995 | #include "iwl-spectrum.h" | 2886 | #include "iwl-spectrum.h" |
@@ -3241,7 +3132,7 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) | |||
3241 | struct sk_buff *beacon; | 3132 | struct sk_buff *beacon; |
3242 | 3133 | ||
3243 | /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ | 3134 | /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ |
3244 | beacon = ieee80211_beacon_get(priv->hw, priv->vif, NULL); | 3135 | beacon = ieee80211_beacon_get(priv->hw, priv->vif); |
3245 | 3136 | ||
3246 | if (!beacon) { | 3137 | if (!beacon) { |
3247 | IWL_ERROR("update beacon failed\n"); | 3138 | IWL_ERROR("update beacon failed\n"); |
@@ -4848,7 +4739,7 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) | |||
4848 | ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; | 4739 | ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; |
4849 | ch_info->min_power = 0; | 4740 | ch_info->min_power = 0; |
4850 | 4741 | ||
4851 | IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x" | 4742 | IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" |
4852 | " %ddBm): Ad-Hoc %ssupported\n", | 4743 | " %ddBm): Ad-Hoc %ssupported\n", |
4853 | ch_info->channel, | 4744 | ch_info->channel, |
4854 | is_channel_a_band(ch_info) ? | 4745 | is_channel_a_band(ch_info) ? |
@@ -4858,7 +4749,6 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) | |||
4858 | CHECK_AND_PRINT(ACTIVE), | 4749 | CHECK_AND_PRINT(ACTIVE), |
4859 | CHECK_AND_PRINT(RADAR), | 4750 | CHECK_AND_PRINT(RADAR), |
4860 | CHECK_AND_PRINT(WIDE), | 4751 | CHECK_AND_PRINT(WIDE), |
4861 | CHECK_AND_PRINT(NARROW), | ||
4862 | CHECK_AND_PRINT(DFS), | 4752 | CHECK_AND_PRINT(DFS), |
4863 | eeprom_ch_info[ch].flags, | 4753 | eeprom_ch_info[ch].flags, |
4864 | eeprom_ch_info[ch].max_power_avg, | 4754 | eeprom_ch_info[ch].max_power_avg, |
@@ -4994,9 +4884,6 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, | |||
4994 | if (scan_ch->type & 1) | 4884 | if (scan_ch->type & 1) |
4995 | scan_ch->type |= (direct_mask << 1); | 4885 | scan_ch->type |= (direct_mask << 1); |
4996 | 4886 | ||
4997 | if (is_channel_narrow(ch_info)) | ||
4998 | scan_ch->type |= (1 << 7); | ||
4999 | |||
5000 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | 4887 | scan_ch->active_dwell = cpu_to_le16(active_dwell); |
5001 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | 4888 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); |
5002 | 4889 | ||
@@ -5843,7 +5730,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) | |||
5843 | if (iwl3945_is_rfkill(priv)) | 5730 | if (iwl3945_is_rfkill(priv)) |
5844 | return; | 5731 | return; |
5845 | 5732 | ||
5846 | ieee80211_start_queues(priv->hw); | 5733 | ieee80211_wake_queues(priv->hw); |
5847 | 5734 | ||
5848 | priv->active_rate = priv->rates_mask; | 5735 | priv->active_rate = priv->rates_mask; |
5849 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; | 5736 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; |
@@ -5869,9 +5756,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) | |||
5869 | /* Configure the adapter for unassociated operation */ | 5756 | /* Configure the adapter for unassociated operation */ |
5870 | iwl3945_commit_rxon(priv); | 5757 | iwl3945_commit_rxon(priv); |
5871 | 5758 | ||
5872 | /* At this point, the NIC is initialized and operational */ | ||
5873 | priv->notif_missed_beacons = 0; | ||
5874 | |||
5875 | iwl3945_reg_txpower_periodic(priv); | 5759 | iwl3945_reg_txpower_periodic(priv); |
5876 | 5760 | ||
5877 | iwl3945_led_register(priv); | 5761 | iwl3945_led_register(priv); |
@@ -5938,7 +5822,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv) | |||
5938 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | 5822 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << |
5939 | STATUS_GEO_CONFIGURED | | 5823 | STATUS_GEO_CONFIGURED | |
5940 | test_bit(STATUS_IN_SUSPEND, &priv->status) << | 5824 | test_bit(STATUS_IN_SUSPEND, &priv->status) << |
5941 | STATUS_IN_SUSPEND; | 5825 | STATUS_IN_SUSPEND | |
5826 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
5827 | STATUS_EXIT_PENDING; | ||
5942 | goto exit; | 5828 | goto exit; |
5943 | } | 5829 | } |
5944 | 5830 | ||
@@ -5953,7 +5839,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv) | |||
5953 | test_bit(STATUS_IN_SUSPEND, &priv->status) << | 5839 | test_bit(STATUS_IN_SUSPEND, &priv->status) << |
5954 | STATUS_IN_SUSPEND | | 5840 | STATUS_IN_SUSPEND | |
5955 | test_bit(STATUS_FW_ERROR, &priv->status) << | 5841 | test_bit(STATUS_FW_ERROR, &priv->status) << |
5956 | STATUS_FW_ERROR; | 5842 | STATUS_FW_ERROR | |
5843 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
5844 | STATUS_EXIT_PENDING; | ||
5957 | 5845 | ||
5958 | spin_lock_irqsave(&priv->lock, flags); | 5846 | spin_lock_irqsave(&priv->lock, flags); |
5959 | iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 5847 | iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
@@ -6085,6 +5973,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv) | |||
6085 | 5973 | ||
6086 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 5974 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
6087 | __iwl3945_down(priv); | 5975 | __iwl3945_down(priv); |
5976 | clear_bit(STATUS_EXIT_PENDING, &priv->status); | ||
6088 | 5977 | ||
6089 | /* tried to restart and config the device for as long as our | 5978 | /* tried to restart and config the device for as long as our |
6090 | * patience could withstand */ | 5979 | * patience could withstand */ |
@@ -6152,6 +6041,26 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) | |||
6152 | "Kill switch must be turned off for " | 6041 | "Kill switch must be turned off for " |
6153 | "wireless networking to work.\n"); | 6042 | "wireless networking to work.\n"); |
6154 | } | 6043 | } |
6044 | |||
6045 | mutex_unlock(&priv->mutex); | ||
6046 | iwl3945_rfkill_set_hw_state(priv); | ||
6047 | } | ||
6048 | |||
6049 | static void iwl3945_bg_set_monitor(struct work_struct *work) | ||
6050 | { | ||
6051 | struct iwl3945_priv *priv = container_of(work, | ||
6052 | struct iwl3945_priv, set_monitor); | ||
6053 | |||
6054 | IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n"); | ||
6055 | |||
6056 | mutex_lock(&priv->mutex); | ||
6057 | |||
6058 | if (!iwl3945_is_ready(priv)) | ||
6059 | IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n"); | ||
6060 | else | ||
6061 | if (iwl3945_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0) | ||
6062 | IWL_ERROR("iwl3945_set_mode() failed\n"); | ||
6063 | |||
6155 | mutex_unlock(&priv->mutex); | 6064 | mutex_unlock(&priv->mutex); |
6156 | } | 6065 | } |
6157 | 6066 | ||
@@ -6388,6 +6297,7 @@ static void iwl3945_bg_up(struct work_struct *data) | |||
6388 | mutex_lock(&priv->mutex); | 6297 | mutex_lock(&priv->mutex); |
6389 | __iwl3945_up(priv); | 6298 | __iwl3945_up(priv); |
6390 | mutex_unlock(&priv->mutex); | 6299 | mutex_unlock(&priv->mutex); |
6300 | iwl3945_rfkill_set_hw_state(priv); | ||
6391 | } | 6301 | } |
6392 | 6302 | ||
6393 | static void iwl3945_bg_restart(struct work_struct *data) | 6303 | static void iwl3945_bg_restart(struct work_struct *data) |
@@ -6511,8 +6421,6 @@ static void iwl3945_bg_post_associate(struct work_struct *data) | |||
6511 | break; | 6421 | break; |
6512 | } | 6422 | } |
6513 | 6423 | ||
6514 | iwl3945_sequence_reset(priv); | ||
6515 | |||
6516 | iwl3945_activate_qos(priv, 0); | 6424 | iwl3945_activate_qos(priv, 0); |
6517 | 6425 | ||
6518 | /* we have just associated, don't start scan too early */ | 6426 | /* we have just associated, don't start scan too early */ |
@@ -6608,6 +6516,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) | |||
6608 | 6516 | ||
6609 | mutex_unlock(&priv->mutex); | 6517 | mutex_unlock(&priv->mutex); |
6610 | 6518 | ||
6519 | iwl3945_rfkill_set_hw_state(priv); | ||
6520 | |||
6611 | if (ret) | 6521 | if (ret) |
6612 | goto out_release_irq; | 6522 | goto out_release_irq; |
6613 | 6523 | ||
@@ -6678,8 +6588,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) | |||
6678 | IWL_DEBUG_MAC80211("leave\n"); | 6588 | IWL_DEBUG_MAC80211("leave\n"); |
6679 | } | 6589 | } |
6680 | 6590 | ||
6681 | static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | 6591 | static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
6682 | struct ieee80211_tx_control *ctl) | ||
6683 | { | 6592 | { |
6684 | struct iwl3945_priv *priv = hw->priv; | 6593 | struct iwl3945_priv *priv = hw->priv; |
6685 | 6594 | ||
@@ -6692,9 +6601,9 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
6692 | } | 6601 | } |
6693 | 6602 | ||
6694 | IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | 6603 | IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, |
6695 | ctl->tx_rate->bitrate); | 6604 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); |
6696 | 6605 | ||
6697 | if (iwl3945_tx_skb(priv, skb, ctl)) | 6606 | if (iwl3945_tx_skb(priv, skb)) |
6698 | dev_kfree_skb_any(skb); | 6607 | dev_kfree_skb_any(skb); |
6699 | 6608 | ||
6700 | IWL_DEBUG_MAC80211("leave\n"); | 6609 | IWL_DEBUG_MAC80211("leave\n"); |
@@ -6837,7 +6746,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) | |||
6837 | return; | 6746 | return; |
6838 | 6747 | ||
6839 | /* The following should be done only at AP bring up */ | 6748 | /* The following should be done only at AP bring up */ |
6840 | if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) { | 6749 | if (!(iwl3945_is_associated(priv))) { |
6841 | 6750 | ||
6842 | /* RXON - unassoc (to set timing command) */ | 6751 | /* RXON - unassoc (to set timing command) */ |
6843 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 6752 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
@@ -6886,6 +6795,9 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) | |||
6886 | * clear sta table, add BCAST sta... */ | 6795 | * clear sta table, add BCAST sta... */ |
6887 | } | 6796 | } |
6888 | 6797 | ||
6798 | /* temporary */ | ||
6799 | static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
6800 | |||
6889 | static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | 6801 | static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, |
6890 | struct ieee80211_vif *vif, | 6802 | struct ieee80211_vif *vif, |
6891 | struct ieee80211_if_conf *conf) | 6803 | struct ieee80211_if_conf *conf) |
@@ -6903,10 +6815,21 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | |||
6903 | return 0; | 6815 | return 0; |
6904 | } | 6816 | } |
6905 | 6817 | ||
6818 | /* handle this temporarily here */ | ||
6819 | if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && | ||
6820 | conf->changed & IEEE80211_IFCC_BEACON) { | ||
6821 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | ||
6822 | if (!beacon) | ||
6823 | return -ENOMEM; | ||
6824 | rc = iwl3945_mac_beacon_update(hw, beacon); | ||
6825 | if (rc) | ||
6826 | return rc; | ||
6827 | } | ||
6828 | |||
6906 | /* XXX: this MUST use conf->mac_addr */ | 6829 | /* XXX: this MUST use conf->mac_addr */ |
6907 | 6830 | ||
6908 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && | 6831 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && |
6909 | (!conf->beacon || !conf->ssid_len)) { | 6832 | (!conf->ssid_len)) { |
6910 | IWL_DEBUG_MAC80211 | 6833 | IWL_DEBUG_MAC80211 |
6911 | ("Leaving in AP mode because HostAPD is not ready.\n"); | 6834 | ("Leaving in AP mode because HostAPD is not ready.\n"); |
6912 | return 0; | 6835 | return 0; |
@@ -6938,7 +6861,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | |||
6938 | if (priv->ibss_beacon) | 6861 | if (priv->ibss_beacon) |
6939 | dev_kfree_skb(priv->ibss_beacon); | 6862 | dev_kfree_skb(priv->ibss_beacon); |
6940 | 6863 | ||
6941 | priv->ibss_beacon = conf->beacon; | 6864 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); |
6942 | } | 6865 | } |
6943 | 6866 | ||
6944 | if (iwl3945_is_rfkill(priv)) | 6867 | if (iwl3945_is_rfkill(priv)) |
@@ -6999,11 +6922,18 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, | |||
6999 | unsigned int *total_flags, | 6922 | unsigned int *total_flags, |
7000 | int mc_count, struct dev_addr_list *mc_list) | 6923 | int mc_count, struct dev_addr_list *mc_list) |
7001 | { | 6924 | { |
7002 | /* | 6925 | struct iwl3945_priv *priv = hw->priv; |
7003 | * XXX: dummy | 6926 | |
7004 | * see also iwl3945_connection_init_rx_config | 6927 | if (changed_flags & (*total_flags) & FIF_OTHER_BSS) { |
7005 | */ | 6928 | IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", |
7006 | *total_flags = 0; | 6929 | IEEE80211_IF_TYPE_MNTR, |
6930 | changed_flags, *total_flags); | ||
6931 | /* queue work 'cuz mac80211 is holding a lock which | ||
6932 | * prevents us from issuing (synchronous) f/w cmds */ | ||
6933 | queue_work(priv->workqueue, &priv->set_monitor); | ||
6934 | } | ||
6935 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | | ||
6936 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | ||
7007 | } | 6937 | } |
7008 | 6938 | ||
7009 | static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, | 6939 | static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, |
@@ -7061,9 +6991,10 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) | |||
7061 | rc = -EAGAIN; | 6991 | rc = -EAGAIN; |
7062 | goto out_unlock; | 6992 | goto out_unlock; |
7063 | } | 6993 | } |
7064 | /* if we just finished scan ask for delay */ | 6994 | /* if we just finished scan ask for delay for a broadcast scan */ |
7065 | if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies + | 6995 | if ((len == 0) && priv->last_scan_jiffies && |
7066 | IWL_DELAY_NEXT_SCAN, jiffies)) { | 6996 | time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, |
6997 | jiffies)) { | ||
7067 | rc = -EAGAIN; | 6998 | rc = -EAGAIN; |
7068 | goto out_unlock; | 6999 | goto out_unlock; |
7069 | } | 7000 | } |
@@ -7150,7 +7081,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
7150 | return rc; | 7081 | return rc; |
7151 | } | 7082 | } |
7152 | 7083 | ||
7153 | static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, | 7084 | static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, |
7154 | const struct ieee80211_tx_queue_params *params) | 7085 | const struct ieee80211_tx_queue_params *params) |
7155 | { | 7086 | { |
7156 | struct iwl3945_priv *priv = hw->priv; | 7087 | struct iwl3945_priv *priv = hw->priv; |
@@ -7224,9 +7155,9 @@ static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, | |||
7224 | q = &txq->q; | 7155 | q = &txq->q; |
7225 | avail = iwl3945_queue_space(q); | 7156 | avail = iwl3945_queue_space(q); |
7226 | 7157 | ||
7227 | stats->data[i].len = q->n_window - avail; | 7158 | stats[i].len = q->n_window - avail; |
7228 | stats->data[i].limit = q->n_window - q->high_mark; | 7159 | stats[i].limit = q->n_window - q->high_mark; |
7229 | stats->data[i].count = q->n_window; | 7160 | stats[i].count = q->n_window; |
7230 | 7161 | ||
7231 | } | 7162 | } |
7232 | spin_unlock_irqrestore(&priv->lock, flags); | 7163 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -7315,8 +7246,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) | |||
7315 | 7246 | ||
7316 | } | 7247 | } |
7317 | 7248 | ||
7318 | static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | 7249 | static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) |
7319 | struct ieee80211_tx_control *control) | ||
7320 | { | 7250 | { |
7321 | struct iwl3945_priv *priv = hw->priv; | 7251 | struct iwl3945_priv *priv = hw->priv; |
7322 | unsigned long flags; | 7252 | unsigned long flags; |
@@ -7398,37 +7328,6 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, | |||
7398 | 7328 | ||
7399 | #endif /* CONFIG_IWL3945_DEBUG */ | 7329 | #endif /* CONFIG_IWL3945_DEBUG */ |
7400 | 7330 | ||
7401 | static ssize_t show_rf_kill(struct device *d, | ||
7402 | struct device_attribute *attr, char *buf) | ||
7403 | { | ||
7404 | /* | ||
7405 | * 0 - RF kill not enabled | ||
7406 | * 1 - SW based RF kill active (sysfs) | ||
7407 | * 2 - HW based RF kill active | ||
7408 | * 3 - Both HW and SW based RF kill active | ||
7409 | */ | ||
7410 | struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; | ||
7411 | int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) | | ||
7412 | (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0); | ||
7413 | |||
7414 | return sprintf(buf, "%i\n", val); | ||
7415 | } | ||
7416 | |||
7417 | static ssize_t store_rf_kill(struct device *d, | ||
7418 | struct device_attribute *attr, | ||
7419 | const char *buf, size_t count) | ||
7420 | { | ||
7421 | struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; | ||
7422 | |||
7423 | mutex_lock(&priv->mutex); | ||
7424 | iwl3945_radio_kill_sw(priv, buf[0] == '1'); | ||
7425 | mutex_unlock(&priv->mutex); | ||
7426 | |||
7427 | return count; | ||
7428 | } | ||
7429 | |||
7430 | static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); | ||
7431 | |||
7432 | static ssize_t show_temperature(struct device *d, | 7331 | static ssize_t show_temperature(struct device *d, |
7433 | struct device_attribute *attr, char *buf) | 7332 | struct device_attribute *attr, char *buf) |
7434 | { | 7333 | { |
@@ -7879,6 +7778,7 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv) | |||
7879 | INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan); | 7778 | INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan); |
7880 | INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill); | 7779 | INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill); |
7881 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); | 7780 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); |
7781 | INIT_WORK(&priv->set_monitor, iwl3945_bg_set_monitor); | ||
7882 | INIT_DELAYED_WORK(&priv->post_associate, iwl3945_bg_post_associate); | 7782 | INIT_DELAYED_WORK(&priv->post_associate, iwl3945_bg_post_associate); |
7883 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); | 7783 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); |
7884 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); | 7784 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); |
@@ -7913,7 +7813,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { | |||
7913 | #endif | 7813 | #endif |
7914 | &dev_attr_power_level.attr, | 7814 | &dev_attr_power_level.attr, |
7915 | &dev_attr_retry_rate.attr, | 7815 | &dev_attr_retry_rate.attr, |
7916 | &dev_attr_rf_kill.attr, | ||
7917 | &dev_attr_rs_window.attr, | 7816 | &dev_attr_rs_window.attr, |
7918 | &dev_attr_statistics.attr, | 7817 | &dev_attr_statistics.attr, |
7919 | &dev_attr_status.attr, | 7818 | &dev_attr_status.attr, |
@@ -7943,7 +7842,6 @@ static struct ieee80211_ops iwl3945_hw_ops = { | |||
7943 | .conf_tx = iwl3945_mac_conf_tx, | 7842 | .conf_tx = iwl3945_mac_conf_tx, |
7944 | .get_tsf = iwl3945_mac_get_tsf, | 7843 | .get_tsf = iwl3945_mac_get_tsf, |
7945 | .reset_tsf = iwl3945_mac_reset_tsf, | 7844 | .reset_tsf = iwl3945_mac_reset_tsf, |
7946 | .beacon_update = iwl3945_mac_beacon_update, | ||
7947 | .hw_scan = iwl3945_mac_hw_scan | 7845 | .hw_scan = iwl3945_mac_hw_scan |
7948 | }; | 7846 | }; |
7949 | 7847 | ||
@@ -7953,7 +7851,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7953 | struct iwl3945_priv *priv; | 7851 | struct iwl3945_priv *priv; |
7954 | struct ieee80211_hw *hw; | 7852 | struct ieee80211_hw *hw; |
7955 | struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); | 7853 | struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); |
7956 | int i; | ||
7957 | unsigned long flags; | 7854 | unsigned long flags; |
7958 | DECLARE_MAC_BUF(mac); | 7855 | DECLARE_MAC_BUF(mac); |
7959 | 7856 | ||
@@ -8001,17 +7898,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8001 | 7898 | ||
8002 | priv->ibss_beacon = NULL; | 7899 | priv->ibss_beacon = NULL; |
8003 | 7900 | ||
8004 | /* Tell mac80211 and its clients (e.g. Wireless Extensions) | 7901 | /* Tell mac80211 our characteristics */ |
8005 | * the range of signal quality values that we'll provide. | 7902 | hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | |
8006 | * Negative values for level/noise indicate that we'll provide dBm. | 7903 | IEEE80211_HW_SIGNAL_DBM | |
8007 | * For WE, at least, non-0 values here *enable* display of values | 7904 | IEEE80211_HW_NOISE_DBM; |
8008 | * in app (iwconfig). */ | ||
8009 | hw->max_rssi = -20; /* signal level, negative indicates dBm */ | ||
8010 | hw->max_noise = -20; /* noise level, negative indicates dBm */ | ||
8011 | hw->max_signal = 100; /* link quality indication (%) */ | ||
8012 | |||
8013 | /* Tell mac80211 our Tx characteristics */ | ||
8014 | hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; | ||
8015 | 7905 | ||
8016 | /* 4 EDCA QOS priorities */ | 7906 | /* 4 EDCA QOS priorities */ |
8017 | hw->queues = 4; | 7907 | hw->queues = 4; |
@@ -8021,9 +7911,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8021 | spin_lock_init(&priv->sta_lock); | 7911 | spin_lock_init(&priv->sta_lock); |
8022 | spin_lock_init(&priv->hcmd_lock); | 7912 | spin_lock_init(&priv->hcmd_lock); |
8023 | 7913 | ||
8024 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) | ||
8025 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); | ||
8026 | |||
8027 | INIT_LIST_HEAD(&priv->free_frames); | 7914 | INIT_LIST_HEAD(&priv->free_frames); |
8028 | 7915 | ||
8029 | mutex_init(&priv->mutex); | 7916 | mutex_init(&priv->mutex); |
@@ -8161,6 +8048,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8161 | pci_save_state(pdev); | 8048 | pci_save_state(pdev); |
8162 | pci_disable_device(pdev); | 8049 | pci_disable_device(pdev); |
8163 | 8050 | ||
8051 | err = iwl3945_rfkill_init(priv); | ||
8052 | if (err) | ||
8053 | IWL_ERROR("Unable to initialize RFKILL system. " | ||
8054 | "Ignoring error: %d\n", err); | ||
8055 | |||
8164 | return 0; | 8056 | return 0; |
8165 | 8057 | ||
8166 | out_free_geos: | 8058 | out_free_geos: |
@@ -8191,8 +8083,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8191 | static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | 8083 | static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) |
8192 | { | 8084 | { |
8193 | struct iwl3945_priv *priv = pci_get_drvdata(pdev); | 8085 | struct iwl3945_priv *priv = pci_get_drvdata(pdev); |
8194 | struct list_head *p, *q; | ||
8195 | int i; | ||
8196 | unsigned long flags; | 8086 | unsigned long flags; |
8197 | 8087 | ||
8198 | if (!priv) | 8088 | if (!priv) |
@@ -8213,16 +8103,9 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
8213 | 8103 | ||
8214 | iwl_synchronize_irq(priv); | 8104 | iwl_synchronize_irq(priv); |
8215 | 8105 | ||
8216 | /* Free MAC hash list for ADHOC */ | ||
8217 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { | ||
8218 | list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { | ||
8219 | list_del(p); | ||
8220 | kfree(list_entry(p, struct iwl3945_ibss_seq, list)); | ||
8221 | } | ||
8222 | } | ||
8223 | |||
8224 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | 8106 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); |
8225 | 8107 | ||
8108 | iwl3945_rfkill_unregister(priv); | ||
8226 | iwl3945_dealloc_ucode_pci(priv); | 8109 | iwl3945_dealloc_ucode_pci(priv); |
8227 | 8110 | ||
8228 | if (priv->rxq.bd) | 8111 | if (priv->rxq.bd) |
@@ -8252,7 +8135,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
8252 | 8135 | ||
8253 | iwl3945_free_channel_map(priv); | 8136 | iwl3945_free_channel_map(priv); |
8254 | iwl3945_free_geos(priv); | 8137 | iwl3945_free_geos(priv); |
8255 | 8138 | kfree(priv->scan); | |
8256 | if (priv->ibss_beacon) | 8139 | if (priv->ibss_beacon) |
8257 | dev_kfree_skb(priv->ibss_beacon); | 8140 | dev_kfree_skb(priv->ibss_beacon); |
8258 | 8141 | ||
@@ -8291,6 +8174,114 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) | |||
8291 | 8174 | ||
8292 | #endif /* CONFIG_PM */ | 8175 | #endif /* CONFIG_PM */ |
8293 | 8176 | ||
8177 | /*************** RFKILL FUNCTIONS **********/ | ||
8178 | #ifdef CONFIG_IWL3945_RFKILL | ||
8179 | /* software rf-kill from user */ | ||
8180 | static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | ||
8181 | { | ||
8182 | struct iwl3945_priv *priv = data; | ||
8183 | int err = 0; | ||
8184 | |||
8185 | if (!priv->rfkill) | ||
8186 | return 0; | ||
8187 | |||
8188 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
8189 | return 0; | ||
8190 | |||
8191 | IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); | ||
8192 | mutex_lock(&priv->mutex); | ||
8193 | |||
8194 | switch (state) { | ||
8195 | case RFKILL_STATE_UNBLOCKED: | ||
8196 | if (iwl3945_is_rfkill_hw(priv)) { | ||
8197 | err = -EBUSY; | ||
8198 | goto out_unlock; | ||
8199 | } | ||
8200 | iwl3945_radio_kill_sw(priv, 0); | ||
8201 | break; | ||
8202 | case RFKILL_STATE_SOFT_BLOCKED: | ||
8203 | iwl3945_radio_kill_sw(priv, 1); | ||
8204 | break; | ||
8205 | default: | ||
8206 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); | ||
8207 | break; | ||
8208 | } | ||
8209 | out_unlock: | ||
8210 | mutex_unlock(&priv->mutex); | ||
8211 | |||
8212 | return err; | ||
8213 | } | ||
8214 | |||
8215 | int iwl3945_rfkill_init(struct iwl3945_priv *priv) | ||
8216 | { | ||
8217 | struct device *device = wiphy_dev(priv->hw->wiphy); | ||
8218 | int ret = 0; | ||
8219 | |||
8220 | BUG_ON(device == NULL); | ||
8221 | |||
8222 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); | ||
8223 | priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); | ||
8224 | if (!priv->rfkill) { | ||
8225 | IWL_ERROR("Unable to allocate rfkill device.\n"); | ||
8226 | ret = -ENOMEM; | ||
8227 | goto error; | ||
8228 | } | ||
8229 | |||
8230 | priv->rfkill->name = priv->cfg->name; | ||
8231 | priv->rfkill->data = priv; | ||
8232 | priv->rfkill->state = RFKILL_STATE_UNBLOCKED; | ||
8233 | priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; | ||
8234 | priv->rfkill->user_claim_unsupported = 1; | ||
8235 | |||
8236 | priv->rfkill->dev.class->suspend = NULL; | ||
8237 | priv->rfkill->dev.class->resume = NULL; | ||
8238 | |||
8239 | ret = rfkill_register(priv->rfkill); | ||
8240 | if (ret) { | ||
8241 | IWL_ERROR("Unable to register rfkill: %d\n", ret); | ||
8242 | goto freed_rfkill; | ||
8243 | } | ||
8244 | |||
8245 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | ||
8246 | return ret; | ||
8247 | |||
8248 | freed_rfkill: | ||
8249 | if (priv->rfkill != NULL) | ||
8250 | rfkill_free(priv->rfkill); | ||
8251 | priv->rfkill = NULL; | ||
8252 | |||
8253 | error: | ||
8254 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | ||
8255 | return ret; | ||
8256 | } | ||
8257 | |||
8258 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) | ||
8259 | { | ||
8260 | if (priv->rfkill) | ||
8261 | rfkill_unregister(priv->rfkill); | ||
8262 | |||
8263 | priv->rfkill = NULL; | ||
8264 | } | ||
8265 | |||
8266 | /* set rf-kill to the right state. */ | ||
8267 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) | ||
8268 | { | ||
8269 | |||
8270 | if (!priv->rfkill) | ||
8271 | return; | ||
8272 | |||
8273 | if (iwl3945_is_rfkill_hw(priv)) { | ||
8274 | rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); | ||
8275 | return; | ||
8276 | } | ||
8277 | |||
8278 | if (!iwl3945_is_rfkill_sw(priv)) | ||
8279 | rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); | ||
8280 | else | ||
8281 | rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); | ||
8282 | } | ||
8283 | #endif | ||
8284 | |||
8294 | /***************************************************************************** | 8285 | /***************************************************************************** |
8295 | * | 8286 | * |
8296 | * driver and module entry point | 8287 | * driver and module entry point |