diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
20 files changed, 441 insertions, 548 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 8b1528e52d43..6be1fe13fa57 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -42,14 +42,11 @@ #include "iwl-3945.h" #include "iwl-helpers.h" -#define IWL_1MB_RATE (128 * 1024) -#define IWL_LED_THRESHOLD (16) -#define IWL_MAX_BLINK_TBL (10) static const struct { u16 brightness; u8 on_time; - u8 of_time; + u8 off_time; } blink_tbl[] = { {300, 25, 25}, @@ -61,9 +58,16 @@ static const struct { {15, 95, 95 }, {10, 110, 110}, {5, 130, 130}, - {0, 167, 167} + {0, 167, 167}, + /*SOLID_ON*/ + {-1, IWL_LED_SOLID, 0} }; +#define IWL_1MB_RATE (128 * 1024) +#define IWL_LED_THRESHOLD (16) +#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/ +#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) + static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, struct iwl3945_cmd *cmd, struct sk_buff *skb) @@ -71,6 +75,10 @@ static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, return 1; } +static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) +{ + return fls(0x000000FF & (u32)brightness); +} /* Send led command */ static int iwl_send_led_cmd(struct iwl3945_priv *priv, @@ -81,49 +89,45 @@ static int iwl_send_led_cmd(struct iwl3945_priv *priv, .len = sizeof(struct iwl3945_led_cmd), .data = led_cmd, .meta.flags = CMD_ASYNC, - .meta.u.callback = iwl3945_led_cmd_callback + .meta.u.callback = iwl3945_led_cmd_callback, }; return iwl3945_send_cmd(priv, &cmd); } + /* Set led on command */ -static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) +static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, + unsigned int idx) { struct iwl3945_led_cmd led_cmd = { .id = led_id, - .on = IWL_LED_SOLID, - .off = 0, .interval = IWL_DEF_LED_INTRVL }; + + BUG_ON(idx > IWL_MAX_BLINK_TBL); + + led_cmd.on = blink_tbl[idx].on_time; + led_cmd.off = blink_tbl[idx].off_time; + return iwl_send_led_cmd(priv, &led_cmd); } + +#if 1 /* Set led on command */ -static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, - enum led_brightness brightness) +static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) { struct iwl3945_led_cmd led_cmd = { .id = led_id, - .on = brightness, - .off = brightness, + .on = IWL_LED_SOLID, + .off = 0, .interval = IWL_DEF_LED_INTRVL }; - if (brightness == LED_FULL) { - led_cmd.on = IWL_LED_SOLID; - led_cmd.off = 0; - } return iwl_send_led_cmd(priv, &led_cmd); } -/* Set led register off */ -static int iwl3945_led_on_reg(struct iwl3945_priv *priv, int led_id) -{ - IWL_DEBUG_LED("led on %d\n", led_id); - return iwl3945_led_on(priv, led_id); -} - /* Set led off command */ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) { @@ -136,27 +140,7 @@ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) IWL_DEBUG_LED("led off %d\n", led_id); return iwl_send_led_cmd(priv, &led_cmd); } - -/* Set led register off */ -static int iwl3945_led_off_reg(struct iwl3945_priv *priv, int led_id) -{ - iwl3945_led_off(priv, led_id); - return 0; -} - -/* Set led blink command */ -static int iwl3945_led_not_solid(struct iwl3945_priv *priv, int led_id, - u8 brightness) -{ - struct iwl3945_led_cmd led_cmd = { - .id = led_id, - .on = brightness, - .off = brightness, - .interval = IWL_DEF_LED_INTRVL - }; - - return iwl_send_led_cmd(priv, &led_cmd); -} +#endif /* @@ -206,8 +190,10 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, led->led_off(priv, IWL_LED_LINK); break; default: - if (led->led_pattern) - led->led_pattern(priv, IWL_LED_LINK, brightness); + if (led->led_pattern) { + int idx = iwl3945_brightness_to_idx(brightness); + led->led_pattern(priv, IWL_LED_LINK, idx); + } break; } } @@ -252,24 +238,20 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv, static inline u8 get_blink_rate(struct iwl3945_priv *priv) { int index; - u8 blink_rate; - - if (priv->rxtxpackets < IWL_LED_THRESHOLD) - index = 10; - else { - for (index = 0; index < IWL_MAX_BLINK_TBL; index++) { - if (priv->rxtxpackets > (blink_tbl[index].brightness * - IWL_1MB_RATE)) - break; - } - } - /* if 0 frame is transfered */ - if ((index == IWL_MAX_BLINK_TBL) || !priv->allow_blinking) - blink_rate = IWL_LED_SOLID; - else - blink_rate = blink_tbl[index].on_time; + u64 current_tpt = priv->rxtxpackets; + s64 tpt = current_tpt - priv->led_tpt; - return blink_rate; + if (tpt < 0) + tpt = -tpt; + priv->led_tpt = current_tpt; + + if (!priv->allow_blinking) + index = IWL_MAX_BLINK_TBL; + else + for (index = 0; index < IWL_MAX_BLINK_TBL; index++) + if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE)) + break; + return index; } static inline int is_rf_kill(struct iwl3945_priv *priv) @@ -285,7 +267,7 @@ static inline int is_rf_kill(struct iwl3945_priv *priv) */ void iwl3945_led_background(struct iwl3945_priv *priv) { - u8 blink_rate; + u8 blink_idx; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { priv->last_blink_time = 0; @@ -298,9 +280,10 @@ void iwl3945_led_background(struct iwl3945_priv *priv) if (!priv->allow_blinking) { priv->last_blink_time = 0; - if (priv->last_blink_rate != IWL_LED_SOLID) { - priv->last_blink_rate = IWL_LED_SOLID; - iwl3945_led_on(priv, IWL_LED_LINK); + if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { + priv->last_blink_rate = IWL_SOLID_BLINK_IDX; + iwl3945_led_pattern(priv, IWL_LED_LINK, + IWL_SOLID_BLINK_IDX); } return; } @@ -309,21 +292,14 @@ void iwl3945_led_background(struct iwl3945_priv *priv) msecs_to_jiffies(1000))) return; - blink_rate = get_blink_rate(priv); + blink_idx = get_blink_rate(priv); /* call only if blink rate change */ - if (blink_rate != priv->last_blink_rate) { - if (blink_rate != IWL_LED_SOLID) { - priv->last_blink_time = jiffies + - msecs_to_jiffies(1000); - iwl3945_led_not_solid(priv, IWL_LED_LINK, blink_rate); - } else { - priv->last_blink_time = 0; - iwl3945_led_on(priv, IWL_LED_LINK); - } - } + if (blink_idx != priv->last_blink_rate) + iwl3945_led_pattern(priv, IWL_LED_LINK, blink_idx); - priv->last_blink_rate = blink_rate; + priv->last_blink_time = jiffies; + priv->last_blink_rate = blink_idx; priv->rxtxpackets = 0; } @@ -337,6 +313,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv) priv->last_blink_rate = 0; priv->rxtxpackets = 0; + priv->led_tpt = 0; priv->last_blink_time = 0; priv->allow_blinking = 0; @@ -344,8 +321,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv) snprintf(name, sizeof(name), "iwl-%s:radio", wiphy_name(priv->hw->wiphy)); - priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on_reg; - priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off_reg; + priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; + priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; ret = iwl3945_led_register_led(priv, @@ -364,8 +341,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv) IWL_LED_TRG_ASSOC, 0, name, trigger); /* for assoc always turn led on */ - priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on_reg; - priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on_reg; + priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; + priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; if (ret) @@ -391,6 +368,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv) trigger = ieee80211_get_tx_led_name(priv->hw); snprintf(name, sizeof(name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); + ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_TX], IWL_LED_TRG_TX, 0, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index b1d2f6b8b259..47b7e0bac802 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -54,7 +54,7 @@ struct iwl3945_led { int (*led_on) (struct iwl3945_priv *priv, int led_id); int (*led_off) (struct iwl3945_priv *priv, int led_id); int (*led_pattern) (struct iwl3945_priv *priv, int led_id, - enum led_brightness brightness); + unsigned int idx); enum led_type type; unsigned int registered; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 94e177a9f51c..c2a76785b665 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -514,6 +514,23 @@ static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, } #endif +/* This is necessary only for a number of statistics, see the caller. */ +static int iwl3945_is_network_packet(struct iwl3945_priv *priv, + struct ieee80211_hdr *header) +{ + /* Filter incoming packets to determine if they are targeted toward + * this network, discarding packets coming from ourselves */ + switch (priv->iw_mode) { + case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ + /* packets to our IBSS update information */ + return !compare_ether_addr(header->addr3, priv->bssid); + case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ + /* packets to our IBSS update information */ + return !compare_ether_addr(header->addr2, priv->bssid); + default: + return 1; + } +} static void iwl3945_add_radiotap(struct iwl3945_priv *priv, struct sk_buff *skb, @@ -608,12 +625,12 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, stats->flag |= RX_FLAG_RADIOTAP; } -static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, +static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb, struct ieee80211_rx_status *stats) { - struct ieee80211_hdr *hdr; struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); short len = le16_to_cpu(rx_hdr->len); @@ -635,8 +652,6 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, /* Set the size of the skb to the size of the frame */ skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); - hdr = (void *)rxb->skb->data; - if (iwl3945_param_hwcrypto) iwl3945_set_decrypted_flag(priv, rxb->skb, le32_to_cpu(rx_end->status), stats); @@ -645,7 +660,7 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats); #ifdef CONFIG_IWL3945_LEDS - if (is_data) + if (ieee80211_is_data(hdr->frame_control)) priv->rxtxpackets += len; #endif ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); @@ -694,7 +709,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, } if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { - iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); + iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); return; } @@ -842,27 +857,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, } } - iwl3945_handle_data_packet(priv, 0, rxb, &rx_status); - break; - - case IEEE80211_FTYPE_CTL: - break; - - case IEEE80211_FTYPE_DATA: { - DECLARE_MAC_BUF(mac1); - DECLARE_MAC_BUF(mac2); - DECLARE_MAC_BUF(mac3); - - if (unlikely(iwl3945_is_duplicate_packet(priv, header))) - IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n", - print_mac(mac1, header->addr1), - print_mac(mac2, header->addr2), - print_mac(mac3, header->addr3)); - else - iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); + case IEEE80211_FTYPE_DATA: + /* fall through */ + default: + iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); break; } - } } int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 9c0a09eaca6f..fa81ba1af3d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -510,8 +510,6 @@ struct iwl3945_ucode { u8 data[0]; /* data in same order as "size" elements */ }; -#define IWL_IBSS_MAC_HASH_SIZE 32 - struct iwl3945_ibss_seq { u8 mac[ETH_ALEN]; u16 seq_num; @@ -569,17 +567,8 @@ extern int iwl3945_send_add_station(struct iwl3945_priv *priv, struct iwl3945_addsta_cmd *sta, u8 flags); extern u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *bssid, int is_ap, u8 flags); -extern int iwl3945_is_network_packet(struct iwl3945_priv *priv, - struct ieee80211_hdr *header); extern int iwl3945_power_init_handle(struct iwl3945_priv *priv); extern int iwl3945_eeprom_init(struct iwl3945_priv *priv); -extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb, - void *data, short len, - struct ieee80211_rx_status *stats, - u16 phy_flags); -extern int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, - struct ieee80211_hdr *header); extern int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv); extern void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq); @@ -805,6 +794,7 @@ struct iwl3945_priv { u8 last_blink_rate; u8 allow_blinking; unsigned int rxtxpackets; + u64 led_tpt; #endif @@ -859,14 +849,6 @@ struct iwl3945_priv { u32 last_beacon_time; u64 last_tsf; - /* Duplicate packet detection */ - u16 last_seq_num; - u16 last_frag_num; - unsigned long last_packet_time; - - /* Hash table for finding stations in IBSS network */ - struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE]; - /* eeprom */ struct iwl3945_eeprom eeprom; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 10f630e1afa6..fce950f4163c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -819,6 +819,7 @@ enum { #define IWL49_NUM_FIFOS 7 #define IWL49_CMD_FIFO_NUM 4 #define IWL49_NUM_QUEUES 16 +#define IWL49_NUM_AMPDU_QUEUES 8 /** * struct iwl_tfd_frame_data diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index c7ebb3bf06f5..3ccb84aa5dbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -2265,9 +2265,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, /* as default allow aggregation for all tids */ lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; -#ifdef CONFIG_MAC80211_DEBUGFS lq_sta->drv = priv; -#endif rs_initialize_lq(priv, conf, sta); } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 04365b39279c..9afecb813716 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -49,9 +49,17 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv); static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); +/* Change firmware file name, using "-" and incrementing number, + * *only* when uCode interface or architecture changes so that it + * is not compatible with earlier drivers. + * This number will also appear in << 8 position of 1st dword of uCode file */ +#define IWL4965_UCODE_API "-2" + + /* module parameters */ static struct iwl_mod_params iwl4965_mod_params = { .num_of_queues = IWL49_NUM_QUEUES, + .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, .enable_qos = 1, .amsdu_size_8K = 1, .restart_fw = 1, @@ -642,6 +650,18 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, data->beacon_count = 0; } +static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, + __le32 *tx_flags) +{ + if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + *tx_flags |= TX_CMD_FLG_RTS_MSK; + *tx_flags &= ~TX_CMD_FLG_CTS_MSK; + } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + *tx_flags &= ~TX_CMD_FLG_RTS_MSK; + *tx_flags |= TX_CMD_FLG_CTS_MSK; + } +} + static void iwl4965_bg_txpower_work(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, @@ -1931,9 +1951,11 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, { int ret = 0; - if (IWL49_FIRST_AMPDU_QUEUE > txq_id) { - IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL49_FIRST_AMPDU_QUEUE); + if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || + (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { + IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + txq_id, IWL49_FIRST_AMPDU_QUEUE, + IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); return -EINVAL; } @@ -2000,9 +2022,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, int ret; u16 ra_tid; - if (IWL49_FIRST_AMPDU_QUEUE > txq_id) - IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL49_FIRST_AMPDU_QUEUE); + if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || + (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { + IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + txq_id, IWL49_FIRST_AMPDU_QUEUE, + IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); + return -EINVAL; + } ra_tid = BUILD_RAxTID(sta_id, tid); @@ -2372,6 +2398,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .build_addsta_hcmd = iwl4965_build_addsta_hcmd, .chain_noise_reset = iwl4965_chain_noise_reset, .gain_computation = iwl4965_gain_computation, + .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, }; static struct iwl_lib_ops iwl4965_lib = { @@ -2434,6 +2461,9 @@ struct iwl_cfg iwl4965_agn_cfg = { .mod_params = &iwl4965_mod_params, }; +/* Module firmware */ +MODULE_FIRMWARE("iwlwifi-4965" IWL4965_UCODE_API ".ucode"); + module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(disable, iwl4965_mod_params.disable, int, 0444); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 4efe0c06b5b2..17d4f31c5934 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -81,6 +81,7 @@ #define IWL50_QUEUE_SIZE 256 #define IWL50_CMD_FIFO_NUM 7 #define IWL50_NUM_QUEUES 20 +#define IWL50_NUM_AMPDU_QUEUES 10 #define IWL50_FIRST_AMPDU_QUEUE 10 #define IWL_sta_id_POS 12 diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 717db0d5ffb3..878d6193b232 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -370,6 +370,16 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv) } } +static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, + __le32 *tx_flags) +{ + if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || + (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) + *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; + else + *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; +} + static struct iwl_sensitivity_ranges iwl5000_sensitivity = { .min_nrg_cck = 95, .max_nrg_cck = 0, @@ -1006,9 +1016,13 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, int ret; u16 ra_tid; - if (IWL50_FIRST_AMPDU_QUEUE > txq_id) - IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE); + if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || + (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { + IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + txq_id, IWL50_FIRST_AMPDU_QUEUE, + IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); + return -EINVAL; + } ra_tid = BUILD_RAxTID(sta_id, tid); @@ -1067,9 +1081,11 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, { int ret; - if (IWL50_FIRST_AMPDU_QUEUE > txq_id) { - IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE); + if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || + (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { + IWL_WARNING("queue number out of range: %d, must be %d to %d\n", + txq_id, IWL50_FIRST_AMPDU_QUEUE, + IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); return -EINVAL; } @@ -1437,6 +1453,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { .build_addsta_hcmd = iwl5000_build_addsta_hcmd, .gain_computation = iwl5000_gain_computation, .chain_noise_reset = iwl5000_chain_noise_reset, + .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, }; static struct iwl_lib_ops iwl5000_lib = { @@ -1490,6 +1507,7 @@ static struct iwl_ops iwl5000_ops = { static struct iwl_mod_params iwl50_mod_params = { .num_of_queues = IWL50_NUM_QUEUES, + .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, .enable_qos = 1, .amsdu_size_8K = 1, .restart_fw = 1, @@ -1506,6 +1524,24 @@ struct iwl_cfg iwl5300_agn_cfg = { .mod_params = &iwl50_mod_params, }; +struct iwl_cfg iwl5100_bg_cfg = { + .name = "5100BG", + .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", + .sku = IWL_SKU_G, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .mod_params = &iwl50_mod_params, +}; + +struct iwl_cfg iwl5100_abg_cfg = { + .name = "5100ABG", + .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", + .sku = IWL_SKU_A|IWL_SKU_G, + .ops = &iwl5000_ops, + .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, + .mod_params = &iwl50_mod_params, +}; + struct iwl_cfg iwl5100_agn_cfg = { .name = "5100AGN", .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index fe05d60ebe63..e9bb1de0ce3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -556,6 +556,8 @@ enum { #define RXON_FLG_CHANNEL_MODE_MSK __constant_cpu_to_le32(0x3 << 25) #define RXON_FLG_CHANNEL_MODE_PURE_40_MSK __constant_cpu_to_le32(0x1 << 25) #define RXON_FLG_CHANNEL_MODE_MIXED_MSK __constant_cpu_to_le32(0x2 << 25) +/* CTS to self (if spec allows) flag */ +#define RXON_FLG_SELF_CTS_EN __constant_cpu_to_le32(0x1<<30) /* rx_config filter flags */ /* accept all data frames */ @@ -723,7 +725,7 @@ struct iwl4965_csa_notification { * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW * value, to cap the CW value. */ -struct iwl4965_ac_qos { +struct iwl_ac_qos { __le16 cw_min; __le16 cw_max; u8 aifsn; @@ -745,9 +747,9 @@ struct iwl4965_ac_qos { * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs * 0: Background, 1: Best Effort, 2: Video, 3: Voice. */ -struct iwl4965_qosparam_cmd { +struct iwl_qosparam_cmd { __le32 qos_flags; - struct iwl4965_ac_qos ac[AC_NUM]; + struct iwl_ac_qos ac[AC_NUM]; } __attribute__ ((packed)); /****************************************************************************** @@ -1139,6 +1141,11 @@ struct iwl4965_rx_mpdu_res_start { /* REPLY_TX Tx flags field */ +/* 1: Use RTS/CTS protocol or CTS-to-self if spec alows it + * before this frame. if CTS-to-self required check + * RXON_FLG_SELF_CTS_EN status. */ +#define TX_CMD_FLG_RTS_CTS_MSK __constant_cpu_to_le32(1 << 0) + /* 1: Use Request-To-Send protocol before this frame. * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */ #define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1) @@ -2092,6 +2099,9 @@ struct iwl_ct_kill_config { * *****************************************************************************/ +#define SCAN_CHANNEL_TYPE_PASSIVE __constant_cpu_to_le32(0) +#define SCAN_CHANNEL_TYPE_ACTIVE __constant_cpu_to_le32(1) + /** * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table * @@ -2115,12 +2125,12 @@ struct iwl_scan_channel { /* * type is defined as: * 0:0 1 = active, 0 = passive - * 1:4 SSID direct bit map; if a bit is set, then corresponding + * 1:20 SSID direct bit map; if a bit is set, then corresponding * SSID IE is transmitted in probe request. - * 5:7 reserved + * 21:31 reserved */ - u8 type; - u8 channel; /* band is selected by iwl4965_scan_cmd "flags" field */ + __le32 type; + __le16 channel; /* band is selected by iwl_scan_cmd "flags" field */ u8 tx_gain; /* gain for analog radio */ u8 dsp_atten; /* gain for DSP */ __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ @@ -2140,9 +2150,9 @@ struct iwl_ssid_ie { u8 ssid[32]; } __attribute__ ((packed)); -#define PROBE_OPTION_MAX 0x4 +#define PROBE_OPTION_MAX 0x14 #define TX_CMD_LIFE_TIME_INFINITE __constant_cpu_to_le32(0xFFFFFFFF) -#define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1) +#define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1) #define IWL_MAX_SCAN_SIZE 1024 /* @@ -2919,7 +2929,7 @@ struct iwl5000_calibration_chain_noise_gain_cmd { * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field), * this command turns it on or off, or sets up a periodic blinking cycle. */ -struct iwl4965_led_cmd { +struct iwl_led_cmd { __le32 interval; /* "interval" in uSec */ u8 id; /* 1: Activity, 2: Link, 3: Tech */ u8 off; /* # intervals off while blinking; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index eee220cf52a2..a44188bf4459 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -825,7 +825,7 @@ int iwl_setup_mac(struct iwl_priv *priv) hw->queues = 4; /* queues to support 11n aggregation */ if (priv->cfg->sku & IWL_SKU_N) - hw->ampdu_queues = 12; + hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues; hw->conf.beacon_int = 100; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index dafd62c7dfd6..db66114f1e56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -70,7 +70,7 @@ struct iwl_host_cmd; struct iwl_cmd; -#define IWLWIFI_VERSION "1.2.26k" +#define IWLWIFI_VERSION "1.3.27k" #define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" #define IWL_PCI_DEVICE(dev, subdev, cfg) \ @@ -93,6 +93,8 @@ struct iwl_hcmd_utils_ops { u16 min_average_noise_antennat_i, u32 min_average_noise); void (*chain_noise_reset)(struct iwl_priv *priv); + void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, + __le32 *tx_flags); }; struct iwl_lib_ops { @@ -157,6 +159,7 @@ struct iwl_mod_params { int debug; /* def: 0 = minimal debug log messages */ int disable_hw_scan; /* def: 0 = use h/w scan */ int num_of_queues; /* def: HW dependent */ + int num_of_ampdu_queues;/* def: HW dependent */ int enable_qos; /* def: 1 = use quality of service */ int disable_11n; /* def: 0 = disable 11n capabilities */ int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c8d3d97cf48d..4d789e353e3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -51,12 +51,8 @@ extern struct iwl_cfg iwl4965_agn_cfg; extern struct iwl_cfg iwl5300_agn_cfg; extern struct iwl_cfg iwl5100_agn_cfg; extern struct iwl_cfg iwl5350_agn_cfg; - -/* Change firmware file name, using "-" and incrementing number, - * *only* when uCode interface or architecture changes so that it - * is not compatible with earlier drivers. - * This number will also appear in << 8 position of 1st dword of uCode file */ -#define IWL4965_UCODE_API "-1" +extern struct iwl_cfg iwl5100_bg_cfg; +extern struct iwl_cfg iwl5100_abg_cfg; /* CT-KILL constants */ #define CT_KILL_THRESHOLD 110 /* in Celsius */ @@ -280,7 +276,7 @@ struct iwl_cmd { struct iwl_cmd_header hdr; /* uCode API */ union { struct iwl_addsta_cmd addsta; - struct iwl4965_led_cmd led; + struct iwl_led_cmd led; u32 flags; u8 val8; u16 val16; @@ -288,7 +284,7 @@ struct iwl_cmd { struct iwl4965_bt_cmd bt; struct iwl4965_rxon_time_cmd rxon_time; struct iwl4965_powertable_cmd powertable; - struct iwl4965_qosparam_cmd qosparam; + struct iwl_qosparam_cmd qosparam; struct iwl_tx_cmd tx; struct iwl4965_tx_beacon_cmd tx_beacon; struct iwl4965_rxon_assoc_cmd rxon_assoc; @@ -433,7 +429,7 @@ struct iwl_ht_info { u8 non_GF_STA_present; }; -union iwl4965_qos_capabity { +union iwl_qos_capabity { struct { u8 edca_count:4; /* bit 0-3 */ u8 q_ack:1; /* bit 4 */ @@ -454,11 +450,11 @@ union iwl4965_qos_capabity { }; /* QoS structures */ -struct iwl4965_qos_info { +struct iwl_qos_info { int qos_enable; int qos_active; - union iwl4965_qos_capabity qos_cap; - struct iwl4965_qosparam_cmd def_qos_parm; + union iwl_qos_capabity qos_cap; + struct iwl_qosparam_cmd def_qos_parm; }; #define STA_PS_STATUS_WAKE 0 @@ -490,8 +486,6 @@ struct iwl_ucode { u8 data[0]; /* data in same order as "size" elements */ }; -#define IWL_IBSS_MAC_HASH_SIZE 32 - struct iwl4965_ibss_seq { u8 mac[ETH_ALEN]; u16 seq_num; @@ -933,7 +927,7 @@ struct iwl_priv { #endif #ifdef CONFIG_IWLWIFI_LEDS - struct iwl4965_led led[IWL_LED_TRG_MAX]; + struct iwl_led led[IWL_LED_TRG_MAX]; unsigned long last_blink_time; u8 last_blink_rate; u8 allow_blinking; @@ -1042,7 +1036,7 @@ struct iwl_priv { u16 assoc_capability; u8 ps_mode; - struct iwl4965_qos_info qos_data; + struct iwl_qos_info qos_data; struct workqueue_struct *workqueue; @@ -1065,7 +1059,6 @@ struct iwl_priv { struct delayed_work init_alive_start; struct delayed_work alive_start; struct delayed_work scan_check; - struct delayed_work post_associate; /* TX Power */ s8 tx_power_user_lmt; s8 tx_power_channel_lmt; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index aa6ad18494ce..899d7a2567a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -44,14 +44,21 @@ #include "iwl-io.h" #include "iwl-helpers.h" -#define IWL_1MB_RATE (128 * 1024) -#define IWL_LED_THRESHOLD (16) -#define IWL_MAX_BLINK_TBL (10) +#ifdef CONFIG_IWLWIFI_DEBUG +static const char *led_type_str[] = { + __stringify(IWL_LED_TRG_TX), + __stringify(IWL_LED_TRG_RX), + __stringify(IWL_LED_TRG_ASSOC), + __stringify(IWL_LED_TRG_RADIO), + NULL +}; +#endif /* CONFIG_IWLWIFI_DEBUG */ + static const struct { u16 tpt; u8 on_time; - u8 of_time; + u8 off_time; } blink_tbl[] = { {300, 25, 25}, @@ -63,26 +70,31 @@ static const struct { {15, 95, 95 }, {10, 110, 110}, {5, 130, 130}, - {0, 167, 167} + {0, 167, 167}, +/* SOLID_ON */ + {-1, IWL_LED_SOLID, 0} }; -static int iwl_led_cmd_callback(struct iwl_priv *priv, - struct iwl_cmd *cmd, struct sk_buff *skb) +#define IWL_1MB_RATE (128 * 1024) +#define IWL_LED_THRESHOLD (16) +#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */ +#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) + +/* [0-256] -> [0..8] FIXME: we need [0..10] */ +static inline int iwl_brightness_to_idx(enum led_brightness brightness) { - return 1; + return fls(0x000000FF & (u32)brightness); } - /* Send led command */ -static int iwl_send_led_cmd(struct iwl_priv *priv, - struct iwl4965_led_cmd *led_cmd) +static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) { struct iwl_host_cmd cmd = { .id = REPLY_LEDS_CMD, - .len = sizeof(struct iwl4965_led_cmd), + .len = sizeof(struct iwl_led_cmd), .data = led_cmd, .meta.flags = CMD_ASYNC, - .meta.u.callback = iwl_led_cmd_callback + .meta.u.callback = NULL, }; u32 reg; @@ -93,33 +105,20 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, return iwl_send_cmd(priv, &cmd); } - -/* Set led on command */ -static int iwl4965_led_on(struct iwl_priv *priv, int led_id) -{ - struct iwl4965_led_cmd led_cmd = { - .id = led_id, - .on = IWL_LED_SOLID, - .off = 0, - .interval = IWL_DEF_LED_INTRVL - }; - return iwl_send_led_cmd(priv, &led_cmd); -} - -/* Set led on command */ +/* Set led pattern command */ static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, - enum led_brightness brightness) + unsigned int idx) { - struct iwl4965_led_cmd led_cmd = { + struct iwl_led_cmd led_cmd = { .id = led_id, - .on = brightness, - .off = brightness, .interval = IWL_DEF_LED_INTRVL }; - if (brightness == LED_FULL) { - led_cmd.on = IWL_LED_SOLID; - led_cmd.off = 0; - } + + BUG_ON(idx > IWL_MAX_BLINK_TBL); + + led_cmd.on = blink_tbl[idx].on_time; + led_cmd.off = blink_tbl[idx].off_time; + return iwl_send_led_cmd(priv, &led_cmd); } @@ -132,10 +131,22 @@ static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) } #if 0 +/* Set led on command */ +static int iwl4965_led_on(struct iwl_priv *priv, int led_id) +{ + struct iwl_led_cmd led_cmd = { + .id = led_id, + .on = IWL_LED_SOLID, + .off = 0, + .interval = IWL_DEF_LED_INTRVL + }; + return iwl_send_led_cmd(priv, &led_cmd); +} + /* Set led off command */ int iwl4965_led_off(struct iwl_priv *priv, int led_id) { - struct iwl4965_led_cmd led_cmd = { + struct iwl_led_cmd led_cmd = { .id = led_id, .on = 0, .off = 0, @@ -155,25 +166,10 @@ static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) return 0; } -/* Set led blink command */ -static int iwl4965_led_not_solid(struct iwl_priv *priv, int led_id, - u8 brightness) -{ - struct iwl4965_led_cmd led_cmd = { - .id = led_id, - .on = brightness, - .off = brightness, - .interval = IWL_DEF_LED_INTRVL - }; - - return iwl_send_led_cmd(priv, &led_cmd); -} - - /* * brightness call back function for Tx/Rx LED */ -static int iwl4965_led_associated(struct iwl_priv *priv, int led_id) +static int iwl_led_associated(struct iwl_priv *priv, int led_id) { if (test_bit(STATUS_EXIT_PENDING, &priv->status) || !test_bit(STATUS_READY, &priv->status)) @@ -189,16 +185,18 @@ static int iwl4965_led_associated(struct iwl_priv *priv, int led_id) /* * brightness call back for association and radio */ -static void iwl4965_led_brightness_set(struct led_classdev *led_cdev, +static void iwl_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct iwl4965_led *led = container_of(led_cdev, - struct iwl4965_led, led_dev); + struct iwl_led *led = container_of(led_cdev, struct iwl_led, led_dev); struct iwl_priv *priv = led->priv; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + + IWL_DEBUG_LED("Led type = %s brightness = %d\n", + led_type_str[led->type], brightness); switch (brightness) { case LED_FULL: if (led->type == IWL_LED_TRG_ASSOC) @@ -215,8 +213,10 @@ static void iwl4965_led_brightness_set(struct led_classdev *led_cdev, led->led_off(priv, IWL_LED_LINK); break; default: - if (led->led_pattern) - led->led_pattern(priv, IWL_LED_LINK, brightness); + if (led->led_pattern) { + int idx = iwl_brightness_to_idx(brightness); + led->led_pattern(priv, IWL_LED_LINK, idx); + } break; } } @@ -226,8 +226,7 @@ static void iwl4965_led_brightness_set(struct led_classdev *led_cdev, /* * Register led class with the system */ -static int iwl_leds_register_led(struct iwl_priv *priv, - struct iwl4965_led *led, +static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, enum led_type type, u8 set_led, const char *name, char *trigger) { @@ -235,7 +234,7 @@ static int iwl_leds_register_led(struct iwl_priv *priv, int ret; led->led_dev.name = name; - led->led_dev.brightness_set = iwl4965_led_brightness_set; + led->led_dev.brightness_set = iwl_led_brightness_set; led->led_dev.default_trigger = trigger; led->priv = priv; @@ -259,32 +258,28 @@ static int iwl_leds_register_led(struct iwl_priv *priv, /* * calculate blink rate according to last 2 sec Tx/Rx activities */ -static inline u8 get_blink_rate(struct iwl_priv *priv) +static int iwl_get_blink_rate(struct iwl_priv *priv) { int i; - u8 blink_rate; - u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes; + u64 current_tpt = priv->tx_stats[2].bytes; + /* FIXME: + priv->rx_stats[2].bytes; */ s64 tpt = current_tpt - priv->led_tpt; if (tpt < 0) /* wrapparound */ tpt = -tpt; + IWL_DEBUG_LED("tpt %lld current_tpt %lld\n", tpt, current_tpt); priv->led_tpt = current_tpt; - if (tpt < IWL_LED_THRESHOLD) { + if (!priv->allow_blinking) i = IWL_MAX_BLINK_TBL; - } else { + else for (i = 0; i < IWL_MAX_BLINK_TBL; i++) if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) break; - } - /* if 0 frame is transfered */ - if ((i == IWL_MAX_BLINK_TBL) || !priv->allow_blinking) - blink_rate = IWL_LED_SOLID; - else - blink_rate = blink_tbl[i].on_time; - return blink_rate; + IWL_DEBUG_LED("LED BLINK IDX=%d", i); + return i; } static inline int is_rf_kill(struct iwl_priv *priv) @@ -300,7 +295,7 @@ static inline int is_rf_kill(struct iwl_priv *priv) */ void iwl_leds_background(struct iwl_priv *priv) { - u8 blink_rate; + u8 blink_idx; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { priv->last_blink_time = 0; @@ -313,9 +308,10 @@ void iwl_leds_background(struct iwl_priv *priv) if (!priv->allow_blinking) { priv->last_blink_time = 0; - if (priv->last_blink_rate != IWL_LED_SOLID) { - priv->last_blink_rate = IWL_LED_SOLID; - iwl4965_led_on(priv, IWL_LED_LINK); + if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { + priv->last_blink_rate = IWL_SOLID_BLINK_IDX; + iwl4965_led_pattern(priv, IWL_LED_LINK, + IWL_SOLID_BLINK_IDX); } return; } @@ -324,21 +320,14 @@ void iwl_leds_background(struct iwl_priv *priv) msecs_to_jiffies(1000))) return; - blink_rate = get_blink_rate(priv); + blink_idx = iwl_get_blink_rate(priv); /* call only if blink rate change */ - if (blink_rate != priv->last_blink_rate) { - if (blink_rate != IWL_LED_SOLID) { - priv->last_blink_time = jiffies + - msecs_to_jiffies(1000); - iwl4965_led_not_solid(priv, IWL_LED_LINK, blink_rate); - } else { - priv->last_blink_time = 0; - iwl4965_led_on(priv, IWL_LED_LINK); - } - } + if (blink_idx != priv->last_blink_rate) + iwl4965_led_pattern(priv, IWL_LED_LINK, blink_idx); - priv->last_blink_rate = blink_rate; + priv->last_blink_time = jiffies; + priv->last_blink_rate = blink_idx; } EXPORT_SYMBOL(iwl_leds_background); @@ -362,10 +351,8 @@ int iwl_leds_register(struct iwl_priv *priv) priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg; priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; - ret = iwl_leds_register_led(priv, - &priv->led[IWL_LED_TRG_RADIO], - IWL_LED_TRG_RADIO, 1, - name, trigger); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], + IWL_LED_TRG_RADIO, 1, name, trigger); if (ret) goto exit_fail; @@ -373,10 +360,9 @@ int iwl_leds_register(struct iwl_priv *priv) snprintf(name, sizeof(name), "iwl-%s:assoc", wiphy_name(priv->hw->wiphy)); - ret = iwl_leds_register_led(priv, - &priv->led[IWL_LED_TRG_ASSOC], - IWL_LED_TRG_ASSOC, 0, - name, trigger); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], + IWL_LED_TRG_ASSOC, 0, name, trigger); + /* for assoc always turn led on */ priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg; priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg; @@ -386,31 +372,26 @@ int iwl_leds_register(struct iwl_priv *priv) goto exit_fail; trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:RX", - wiphy_name(priv->hw->wiphy)); + snprintf(name, sizeof(name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy)); - ret = iwl_leds_register_led(priv, - &priv->led[IWL_LED_TRG_RX], - IWL_LED_TRG_RX, 0, - name, trigger); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], + IWL_LED_TRG_RX, 0, name, trigger); - priv->led[IWL_LED_TRG_RX].led_on = iwl4965_led_associated; - priv->led[IWL_LED_TRG_RX].led_off = iwl4965_led_associated; + priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; + priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern; if (ret) goto exit_fail; trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:TX", - wiphy_name(priv->hw->wiphy)); - ret = iwl_leds_register_led(priv, - &priv->led[IWL_LED_TRG_TX], - IWL_LED_TRG_TX, 0, - name, trigger); - priv->led[IWL_LED_TRG_TX].led_on = iwl4965_led_associated; - priv->led[IWL_LED_TRG_TX].led_off = iwl4965_led_associated; + snprintf(name, sizeof(name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], + IWL_LED_TRG_TX, 0, name, trigger); + + priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; + priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern; if (ret) @@ -425,7 +406,7 @@ exit_fail: EXPORT_SYMBOL(iwl_leds_register); /* unregister led class */ -static void iwl_leds_unregister_led(struct iwl4965_led *led, u8 set_led) +static void iwl_leds_unregister_led(struct iwl_led *led, u8 set_led) { if (!led->registered) return; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 5bb04128cd65..1980ae5a7e82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -49,14 +49,13 @@ enum led_type { }; -struct iwl4965_led { +struct iwl_led { struct iwl_priv *priv; struct led_classdev led_dev; int (*led_on) (struct iwl_priv *priv, int led_id); int (*led_off) (struct iwl_priv *priv, int led_id); - int (*led_pattern) (struct iwl_priv *priv, int led_id, - enum led_brightness brightness); + int (*led_pattern) (struct iwl_priv *priv, int led_id, unsigned int idx); enum led_type type; unsigned int registered; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 3e8500ecf598..e2d9afba38a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -29,6 +29,7 @@ #include <linux/etherdevice.h> #include <net/mac80211.h> +#include <asm/unaligned.h> #include "iwl-eeprom.h" #include "iwl-dev.h" #include "iwl-core.h" @@ -829,23 +830,22 @@ static void iwl_add_radiotap(struct iwl_priv *priv, iwl4965_rt->rt_hdr.it_pad = 0; /* total header + data */ - put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)), - &iwl4965_rt->rt_hdr.it_len); + put_unaligned_le16(sizeof(*iwl4965_rt), &iwl4965_rt->rt_hdr.it_len); /* Indicate all the fields we add to the radiotap header */ - put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | - (1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | - (1 << IEEE80211_RADIOTAP_ANTENNA)), - &iwl4965_rt->rt_hdr.it_present); + put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) | + (1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_CHANNEL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | + (1 << IEEE80211_RADIOTAP_ANTENNA), + &(iwl4965_rt->rt_hdr.it_present)); /* Zero the flags, we'll add to them as we go */ iwl4965_rt->rt_flags = 0; - put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf); + put_unaligned_le64(tsf, &iwl4965_rt->rt_tsf); iwl4965_rt->rt_dbmsignal = signal; iwl4965_rt->rt_dbmnoise = noise; @@ -853,17 +853,14 @@ static void iwl_add_radiotap(struct iwl_priv *priv, /* Convert the channel frequency and set the flags */ put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz); if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) - put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_5GHZ), - &iwl4965_rt->rt_chbitmask); + put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, + &iwl4965_rt->rt_chbitmask); else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) - put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK | - IEEE80211_CHAN_2GHZ), - &iwl4965_rt->rt_chbitmask); + put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, + &iwl4965_rt->rt_chbitmask); else /* 802.11g */ - put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_2GHZ), - &iwl4965_rt->rt_chbitmask); + put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, + &iwl4965_rt->rt_chbitmask); if (rate == -1) iwl4965_rt->rt_rate = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5b420b43af5c..efc750d2fc5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -38,8 +38,11 @@ /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after * sending probe req. This should be set long enough to hear probe responses * from more than one AP. */ -#define IWL_ACTIVE_DWELL_TIME_24 (20) /* all times in msec */ -#define IWL_ACTIVE_DWELL_TIME_52 (10) +#define IWL_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */ +#define IWL_ACTIVE_DWELL_TIME_52 (20) + +#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3) +#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2) /* For faster active scanning, scan will move to the next channel if fewer than * PLCP_QUIET_THRESH packets are heard on this channel within @@ -48,7 +51,7 @@ * no other traffic). * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ #define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ -#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(5) /* msec */ +#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. * Must be set longer than active dwell time. @@ -58,10 +61,15 @@ #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 +#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) + + static int scan_tx_ant[3] = { RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK }; + + static int iwl_is_empty_essid(const char *essid, int essid_len) { /* Single white space is for Linksys APs */ @@ -226,8 +234,9 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv, "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", notif->channel, notif->band ? "bg" : "a", - notif->tsf_high, - notif->tsf_low, notif->status, notif->beacon_timer); + le32_to_cpu(notif->tsf_high), + le32_to_cpu(notif->tsf_low), + notif->status, notif->beacon_timer); } /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ @@ -332,19 +341,21 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) + enum ieee80211_band band, + u8 n_probes) { if (band == IEEE80211_BAND_5GHZ) - return IWL_ACTIVE_DWELL_TIME_52; + return IWL_ACTIVE_DWELL_TIME_52 + + IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1); else - return IWL_ACTIVE_DWELL_TIME_24; + return IWL_ACTIVE_DWELL_TIME_24 + + IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); } static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) + enum ieee80211_band band) { - u16 active = iwl_get_active_dwell_time(priv, band); - u16 passive = (band != IEEE80211_BAND_5GHZ) ? + u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -358,15 +369,12 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; } - if (passive <= active) - passive = active + 1; - return passive; } static int iwl_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, - u8 is_active, u8 direct_mask, + u8 is_active, u8 n_probes, struct iwl_scan_channel *scan_ch) { const struct ieee80211_channel *channels = NULL; @@ -375,6 +383,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, u16 passive_dwell = 0; u16 active_dwell = 0; int added, i; + u16 channel; sband = iwl_get_hw_mode(priv, band); if (!sband) @@ -382,31 +391,35 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, channels = sband->channels; - active_dwell = iwl_get_active_dwell_time(priv, band); + active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); passive_dwell = iwl_get_passive_dwell_time(priv, band); + if (passive_dwell <= active_dwell) + passive_dwell = active_dwell + 1; + for (i = 0, added = 0; i < sband->n_channels; i++) { if (channels[i].flags & IEEE80211_CHAN_DISABLED) continue; - scan_ch->channel = + channel = ieee80211_frequency_to_channel(channels[i].center_freq); + scan_ch->channel = cpu_to_le16(channel); - ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); + ch_info = iwl_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", - scan_ch->channel); + channel); continue; } if (!is_active || is_channel_passive(ch_info) || (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) - scan_ch->type = 0; + scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; else - scan_ch->type = 1; + scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; - if (scan_ch->type & 1) - scan_ch->type |= (direct_mask << 1); + if ((scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) && n_probes) + scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); scan_ch->active_dwell = cpu_to_le16(active_dwell); scan_ch->passive_dwell = cpu_to_le16(passive_dwell); @@ -414,20 +427,20 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, /* Set txpower levels to defaults */ scan_ch->dsp_atten = 110; + /* NOTE: if we were doing 6Mb OFDM for scans we'd use + * power level: + * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; + */ if (band == IEEE80211_BAND_5GHZ) scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; - else { + else scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level: - * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; - */ - } - IWL_DEBUG_SCAN("Scanning %d [%s %d]\n", - scan_ch->channel, - (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE", - (scan_ch->type & 1) ? + IWL_DEBUG_SCAN("Scanning ch=%d prob=0x%X [%s %d]\n", + channel, le32_to_cpu(scan_ch->type), + (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? + "ACTIVE" : "PASSIVE", + (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? active_dwell : passive_dwell); scan_ch++; @@ -673,7 +686,7 @@ static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band) break; } } - + IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind); return scan_tx_ant[ind]; } @@ -693,7 +706,7 @@ static void iwl_bg_request_scan(struct work_struct *data) u32 tx_ant; u16 cmd_len; enum ieee80211_band band; - u8 direct_mask; + u8 n_probes = 2; u8 rx_chain = 0x7; /* bitmap: ABC chains */ conf = ieee80211_get_hw_conf(priv->hw); @@ -793,17 +806,16 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->direct_scan[0].len = priv->direct_ssid_len; memcpy(scan->direct_scan[0].ssid, priv->direct_ssid, priv->direct_ssid_len); - direct_mask = 1; + n_probes++; } else if (!iwl_is_associated(priv) && priv->essid_len) { IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n", iwl_escape_essid(priv->essid, priv->essid_len)); scan->direct_scan[0].id = WLAN_EID_SSID; scan->direct_scan[0].len = priv->essid_len; memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); - direct_mask = 1; + n_probes++; } else { IWL_DEBUG_SCAN("Start indirect scan.\n"); - direct_mask = 0; } scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; @@ -860,16 +872,11 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | RXON_FILTER_BCON_AWARE_MSK); - if (direct_mask) - scan->channel_count = - iwl_get_channels_for_scan(priv, band, 1, /* active */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); - else - scan->channel_count = - iwl_get_channels_for_scan(priv, band, 0, /* passive */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + scan->channel_count = + iwl_get_channels_for_scan(priv, band, 1, /* active */ + n_probes, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + if (scan->channel_count == 0) { IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); goto done; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 0be2a71990b0..9b50b1052b09 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -601,13 +601,7 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; } - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { - tx_flags |= TX_CMD_FLG_RTS_MSK; - tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { - tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_flags |= TX_CMD_FLG_CTS_MSK; - } + priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 1a7d18fea89d..4a22d3fba75b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2035,36 +2035,6 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode) return rc; } -int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) -{ - /* Filter incoming packets to determine if they are targeted toward - * this network, discarding packets coming from ourselves */ - switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ - /* packets from our adapter are dropped (echo) */ - if (!compare_ether_addr(header->addr2, priv->mac_addr)) - return 0; - /* {broad,multi}cast packets to our IBSS go through */ - if (is_multicast_ether_addr(header->addr1)) - return !compare_ether_addr(header->addr3, priv->bssid); - /* packets to our adapter go through */ - return !compare_ether_addr(header->addr1, priv->mac_addr); - case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ - /* packets from our adapter are dropped (echo) */ - if (!compare_ether_addr(header->addr3, priv->mac_addr)) - return 0; - /* {broad,multi}cast packets to our BSS go through */ - if (is_multicast_ether_addr(header->addr1)) - return !compare_ether_addr(header->addr2, priv->bssid); - /* packets to our adapter go through */ - return !compare_ether_addr(header->addr1, priv->mac_addr); - default: - return 1; - } - - return 1; -} - /** * iwl3945_scan_cancel - Cancel any currently executing HW scan * @@ -2117,20 +2087,6 @@ static int iwl3945_scan_cancel_timeout(struct iwl3945_priv *priv, unsigned long return ret; } -static void iwl3945_sequence_reset(struct iwl3945_priv *priv) -{ - /* Reset ieee stats */ - - /* We don't reset the net_device_stats (ieee->stats) on - * re-association */ - - priv->last_seq_num = -1; - priv->last_frag_num = -1; - priv->last_packet_time = 0; - - iwl3945_scan_cancel(priv); -} - #define MAX_UCODE_BEACON_INTERVAL 1024 #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) @@ -2925,72 +2881,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, } } -#define IWL_PACKET_RETRY_TIME HZ - -int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) -{ - u16 sc = le16_to_cpu(header->seq_ctrl); - u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4; - u16 frag = sc & IEEE80211_SCTL_FRAG; - u16 *last_seq, *last_frag; - unsigned long *last_time; - - switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_IBSS:{ - struct list_head *p; - struct iwl3945_ibss_seq *entry = NULL; - u8 *mac = header->addr2; - int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1); - - __list_for_each(p, &priv->ibss_mac_hash[index]) { - entry = list_entry(p, struct iwl3945_ibss_seq, list); - if (!compare_ether_addr(entry->mac, mac)) - break; - } - if (p == &priv->ibss_mac_hash[index]) { - entry = kzalloc(sizeof(*entry), GFP_ATOMIC); - if (!entry) { - IWL_ERROR("Cannot malloc new mac entry\n"); - return 0; - } - memcpy(entry->mac, mac, ETH_ALEN); - entry->seq_num = seq; - entry->frag_num = frag; - entry->packet_time = jiffies; - list_add(&entry->list, &priv->ibss_mac_hash[index]); - return 0; - } - last_seq = &entry->seq_num; - last_frag = &entry->frag_num; - last_time = &entry->packet_time; - break; - } - case IEEE80211_IF_TYPE_STA: - last_seq = &priv->last_seq_num; - last_frag = &priv->last_frag_num; - last_time = &priv->last_packet_time; - break; - default: - return 0; - } - if ((*last_seq == seq) && - time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) { - if (*last_frag == frag) - goto drop; - if (*last_frag + 1 != frag) - /* out-of-order fragment */ - goto drop; - } else - *last_seq = seq; - - *last_frag = frag; - *last_time = jiffies; - return 0; - - drop: - return 1; -} - #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT #include "iwl-spectrum.h" @@ -6531,8 +6421,6 @@ static void iwl3945_bg_post_associate(struct work_struct *data) break; } - iwl3945_sequence_reset(priv); - iwl3945_activate_qos(priv, 0); /* we have just associated, don't start scan too early */ @@ -6907,6 +6795,9 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) * clear sta table, add BCAST sta... */ } +/* temporary */ +static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); + static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf) @@ -6924,10 +6815,21 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, return 0; } + /* handle this temporarily here */ + if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + conf->changed & IEEE80211_IFCC_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + if (!beacon) + return -ENOMEM; + rc = iwl3945_mac_beacon_update(hw, beacon); + if (rc) + return rc; + } + /* XXX: this MUST use conf->mac_addr */ if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && - (!conf->beacon || !conf->ssid_len)) { + (!conf->ssid_len)) { IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n"); return 0; @@ -6959,7 +6861,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = conf->beacon; + priv->ibss_beacon = ieee80211_beacon_get(hw, vif); } if (iwl3945_is_rfkill(priv)) @@ -7940,7 +7842,6 @@ static struct ieee80211_ops iwl3945_hw_ops = { .conf_tx = iwl3945_mac_conf_tx, .get_tsf = iwl3945_mac_get_tsf, .reset_tsf = iwl3945_mac_reset_tsf, - .beacon_update = iwl3945_mac_beacon_update, .hw_scan = iwl3945_mac_hw_scan }; @@ -7950,7 +7851,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e struct iwl3945_priv *priv; struct ieee80211_hw *hw; struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); - int i; unsigned long flags; DECLARE_MAC_BUF(mac); @@ -8011,9 +7911,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); - for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) - INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); - INIT_LIST_HEAD(&priv->free_frames); mutex_init(&priv->mutex); @@ -8186,8 +8083,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) { struct iwl3945_priv *priv = pci_get_drvdata(pdev); - struct list_head *p, *q; - int i; unsigned long flags; if (!priv) @@ -8208,14 +8103,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl_synchronize_irq(priv); - /* Free MAC hash list for ADHOC */ - for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { - list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { - list_del(p); - kfree(list_entry(p, struct iwl3945_ibss_seq, list)); - } - } - sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); iwl3945_rfkill_unregister(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 7f65d9123b2a..71f5da3fe5c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -250,6 +250,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) /* always get timestamp with Rx frame */ priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; + /* allow CTS-to-self if possible. this is relevant only for + * 5000, but will not damage 4965 */ + priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; ret = iwl4965_check_rxon_cmd(&priv->staging_rxon); if (ret) { @@ -325,16 +328,6 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) if (!priv->error_recovering) priv->start_calib = 0; - iwl_init_sensitivity(priv); - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ - ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); - if (ret) { - IWL_ERROR("Error sending TX power (%d)\n", ret); - return ret; - } - /* Add the broadcast address so we can send broadcast frames */ if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == IWL_INVALID_STATION) { @@ -370,6 +363,16 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); } + iwl_init_sensitivity(priv); + + /* If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames */ + ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); + if (ret) { + IWL_ERROR("Error sending TX power (%d)\n", ret); + return ret; + } + return 0; } @@ -572,25 +575,14 @@ static void iwl4965_ht_conf(struct iwl_priv *priv, /* * QoS support */ -static int iwl4965_send_qos_params_command(struct iwl_priv *priv, - struct iwl4965_qosparam_cmd *qos) -{ - - return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM, - sizeof(struct iwl4965_qosparam_cmd), qos); -} - -static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) +static void iwl_activate_qos(struct iwl_priv *priv, u8 force) { - unsigned long flags; - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (!priv->qos_data.qos_enable) return; - spin_lock_irqsave(&priv->lock, flags); priv->qos_data.def_qos_parm.qos_flags = 0; if (priv->qos_data.qos_cap.q_AP.queue_request && @@ -604,15 +596,14 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) if (priv->current_ht_config.is_ht) priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; - spin_unlock_irqrestore(&priv->lock, flags); - if (force || iwl_is_associated(priv)) { IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", priv->qos_data.qos_active, priv->qos_data.def_qos_parm.qos_flags); - iwl4965_send_qos_params_command(priv, - &(priv->qos_data.def_qos_parm)); + iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, + sizeof(struct iwl_qosparam_cmd), + &priv->qos_data.def_qos_parm, NULL); } } @@ -2421,6 +2412,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) struct ieee80211_conf *conf = NULL; int ret = 0; DECLARE_MAC_BUF(mac); + unsigned long flags; if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__); @@ -2510,25 +2502,15 @@ static void iwl4965_post_associate(struct iwl_priv *priv) if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) priv->assoc_station_added = 1; - iwl4965_activate_qos(priv, 0); + spin_lock_irqsave(&priv->lock, flags); + iwl_activate_qos(priv, 0); + spin_unlock_irqrestore(&priv->lock, flags); iwl_power_update_mode(priv, 0); /* we have just associated, don't start scan too early */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; } - -static void iwl4965_bg_post_associate(struct work_struct *data) -{ - struct iwl_priv *priv = container_of(data, struct iwl_priv, - post_associate.work); - - mutex_lock(&priv->mutex); - iwl4965_post_associate(priv); - mutex_unlock(&priv->mutex); - -} - static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); static void iwl_bg_scan_completed(struct work_struct *work) @@ -2659,7 +2641,6 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw) */ mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); - cancel_delayed_work(&priv->post_associate); mutex_unlock(&priv->mutex); } @@ -2855,6 +2836,7 @@ out: static void iwl4965_config_ap(struct iwl_priv *priv) { int ret = 0; + unsigned long flags; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -2902,7 +2884,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); - iwl4965_activate_qos(priv, 1); + spin_lock_irqsave(&priv->lock, flags); + iwl_activate_qos(priv, 1); + spin_unlock_irqrestore(&priv->lock, flags); iwl_rxon_add_station(priv, iwl_bcast_addr, 0); } iwl4965_send_beacon_cmd(priv); @@ -2912,6 +2896,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv) * clear sta table, add BCAST sta... */ } +/* temporary */ +static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); + static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf) @@ -2929,8 +2916,18 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, return 0; } + if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + conf->changed & IEEE80211_IFCC_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + if (!beacon) + return -ENOMEM; + rc = iwl4965_mac_beacon_update(hw, beacon); + if (rc) + return rc; + } + if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && - (!conf->beacon || !conf->ssid_len)) { + (!conf->ssid_len)) { IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n"); return 0; @@ -2962,7 +2959,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = conf->beacon; + priv->ibss_beacon = ieee80211_beacon_get(hw, vif); } if (iwl_is_rfkill(priv)) @@ -3048,7 +3045,6 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, if (iwl_is_ready_rf(priv)) { iwl_scan_cancel_timeout(priv, 100); - cancel_delayed_work(&priv->post_associate); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); } @@ -3338,15 +3334,12 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; priv->qos_data.qos_active = 1; - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); if (priv->iw_mode == IEEE80211_IF_TYPE_AP) - iwl4965_activate_qos(priv, 1); + iwl_activate_qos(priv, 1); else if (priv->assoc_id && iwl_is_associated(priv)) - iwl4965_activate_qos(priv, 0); + iwl_activate_qos(priv, 0); - mutex_unlock(&priv->mutex); + spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_MAC80211("leave\n"); return 0; @@ -3413,8 +3406,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) iwl_reset_qos(priv); - cancel_delayed_work(&priv->post_associate); - spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = 0; priv->assoc_capability = 0; @@ -4016,7 +4007,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update); INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor); INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); - INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate); INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); @@ -4043,7 +4033,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); - cancel_delayed_work(&priv->post_associate); cancel_work_sync(&priv->beacon_update); del_timer_sync(&priv->statistics_periodic); } @@ -4090,7 +4079,6 @@ static struct ieee80211_ops iwl4965_hw_ops = { .get_tx_stats = iwl4965_mac_get_tx_stats, .conf_tx = iwl4965_mac_conf_tx, .reset_tsf = iwl4965_mac_reset_tsf, - .beacon_update = iwl4965_mac_beacon_update, .bss_info_changed = iwl4965_bss_info_changed, .ampdu_action = iwl4965_mac_ampdu_action, .hw_scan = iwl4965_mac_hw_scan @@ -4409,8 +4397,16 @@ static struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, #ifdef CONFIG_IWL5000 - {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, + {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, + {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)}, + {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, + {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)}, + {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)}, {IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)}, #endif /* CONFIG_IWL5000 */ {0} |