diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 1082 |
1 files changed, 299 insertions, 783 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index cbaeaf18649..1a5678fe422 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -46,6 +46,7 @@ #include <asm/div64.h> +#include "iwl-3945-core.h" #include "iwl-3945.h" #include "iwl-helpers.h" @@ -69,7 +70,7 @@ static int iwl3945_param_disable; /* def: 0 = enable radio */ static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */ -int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ +int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */ /* * module name, copyright, version, etc. @@ -91,15 +92,10 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ #define VS #endif -#define IWLWIFI_VERSION "1.2.23k" VD VS -#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" +#define IWLWIFI_VERSION "1.2.26k" VD VS +#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" #define DRV_VERSION IWLWIFI_VERSION -/* 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 IWL3945_UCODE_API "-1" MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_VERSION(DRV_VERSION); @@ -116,16 +112,10 @@ static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr) return NULL; } -static const struct ieee80211_hw_mode *iwl3945_get_hw_mode( - struct iwl3945_priv *priv, int mode) +static const struct ieee80211_supported_band *iwl3945_get_band( + struct iwl3945_priv *priv, enum ieee80211_band band) { - int i; - - for (i = 0; i < 3; i++) - if (priv->modes[i].mode == mode) - return &priv->modes[i]; - - return NULL; + return priv->hw->wiphy->bands[band]; } static int iwl3945_is_empty_essid(const char *essid, int essid_len) @@ -168,17 +158,6 @@ static const char *iwl3945_escape_essid(const char *essid, u8 essid_len) return escaped; } -static void iwl3945_print_hex_dump(int level, void *p, u32 len) -{ -#ifdef CONFIG_IWL3945_DEBUG - if (!(iwl3945_debug_level & level)) - return; - - print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, - p, len, 1); -#endif -} - /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** * DMA services * @@ -204,7 +183,7 @@ static void iwl3945_print_hex_dump(int level, void *p, u32 len) * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused. ***************************************************/ -static int iwl3945_queue_space(const struct iwl3945_queue *q) +int iwl3945_queue_space(const struct iwl3945_queue *q) { int s = q->read_ptr - q->write_ptr; @@ -220,33 +199,14 @@ static int iwl3945_queue_space(const struct iwl3945_queue *q) return s; } -/** - * iwl3945_queue_inc_wrap - increment queue index, wrap back to beginning - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl3945_queue_inc_wrap(int index, int n_bd) -{ - return ++index & (n_bd - 1); -} - -/** - * iwl3945_queue_dec_wrap - increment queue index, wrap back to end - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl3945_queue_dec_wrap(int index, int n_bd) -{ - return --index & (n_bd - 1); -} - -static inline int x2_queue_used(const struct iwl3945_queue *q, int i) +int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i) { return q->write_ptr > q->read_ptr ? (i >= q->read_ptr && i < q->write_ptr) : !(i < q->read_ptr && i >= q->write_ptr); } + static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge) { /* This is for scan command, the big buffer at end of command array */ @@ -267,8 +227,8 @@ static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q q->n_window = slots_num; q->id = id; - /* count must be power-of-two size, otherwise iwl3945_queue_inc_wrap - * and iwl3945_queue_dec_wrap are broken. */ + /* count must be power-of-two size, otherwise iwl_queue_inc_wrap + * and iwl_queue_dec_wrap are broken. */ BUG_ON(!is_power_of_2(count)); /* slots_num must be power-of-two size, otherwise @@ -368,7 +328,7 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv, txq->need_update = 0; /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise - * iwl3945_queue_inc_wrap and iwl3945_queue_dec_wrap are broken. */ + * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); /* Initialize queue high/low-water, head/tail indexes */ @@ -399,7 +359,7 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t /* first, empty all BD's */ for (; q->write_ptr != q->read_ptr; - q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) iwl3945_hw_txq_free_tfd(priv, txq); len = sizeof(struct iwl3945_cmd) * q->n_window; @@ -547,7 +507,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 station->sta.sta.sta_id = index; station->sta.station_flags = 0; - if (priv->phymode == MODE_IEEE80211A) + if (priv->band == IEEE80211_BAND_5GHZ) rate = IWL_RATE_6M_PLCP; else rate = IWL_RATE_1M_PLCP; @@ -738,7 +698,7 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c txq->need_update = 1; /* Increment and update queue's write index */ - q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd); + q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); ret = iwl3945_tx_queue_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->hcmd_lock, flags); @@ -773,17 +733,17 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_ { int cmd_idx; int ret; - static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */ BUG_ON(cmd->meta.flags & CMD_ASYNC); /* A synchronous command can not have a callback set. */ BUG_ON(cmd->meta.u.callback != NULL); - if (atomic_xchg(&entry, 1)) { + if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { IWL_ERROR("Error sending %s: Already sending a host command\n", get_cmd_string(cmd->id)); - return -EBUSY; + ret = -EBUSY; + goto out; } set_bit(STATUS_HCMD_ACTIVE, &priv->status); @@ -853,7 +813,7 @@ fail: cmd->meta.u.skb = NULL; } out: - atomic_set(&entry, 0); + clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); return ret; } @@ -894,35 +854,37 @@ int iwl3945_send_statistics_request(struct iwl3945_priv *priv) /** * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON - * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz - * @channel: Any channel valid for the requested phymode + * @band: 2.4 or 5 GHz band + * @channel: Any channel valid for the requested band - * In addition to setting the staging RXON, priv->phymode is also set. + * In addition to setting the staging RXON, priv->band is also set. * * NOTE: Does not commit to the hardware; it sets appropriate bit fields - * in the staging RXON flag structure based on the phymode + * in the staging RXON flag structure based on the band */ -static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, u8 phymode, u16 channel) +static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, + enum ieee80211_band band, + u16 channel) { - if (!iwl3945_get_channel_info(priv, phymode, channel)) { + if (!iwl3945_get_channel_info(priv, band, channel)) { IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", - channel, phymode); + channel, band); return -EINVAL; } if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && - (priv->phymode == phymode)) + (priv->band == band)) return 0; priv->staging_rxon.channel = cpu_to_le16(channel); - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; else priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->phymode = phymode; + priv->band = band; - IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode); + IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band); return 0; } @@ -1210,8 +1172,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) return -EIO; } - /* Init the hardware's rate fallback order based on the - * phymode */ + /* Init the hardware's rate fallback order based on the band */ rc = iwl3945_init_hw_rate_table(priv); if (rc) { IWL_ERROR("Error setting HW rate table: %02X\n", rc); @@ -1635,151 +1596,6 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) return 0; } -/****************************************************************************** - * - * Misc. internal state and helper functions - * - ******************************************************************************/ -#ifdef CONFIG_IWL3945_DEBUG - -/** - * iwl3945_report_frame - dump frame to syslog during debug sessions - * - * You may hack this function to show different aspects of received frames, - * including selective frame dumps. - * group100 parameter selects whether to show 1 out of 100 good frames. - */ -void iwl3945_report_frame(struct iwl3945_priv *priv, - struct iwl3945_rx_packet *pkt, - struct ieee80211_hdr *header, int group100) -{ - u32 to_us; - u32 print_summary = 0; - u32 print_dump = 0; /* set to 1 to dump all frames' contents */ - u32 hundred = 0; - u32 dataframe = 0; - u16 fc; - u16 seq_ctl; - u16 channel; - u16 phy_flags; - int rate_sym; - u16 length; - u16 status; - u16 bcn_tmr; - u32 tsf_low; - u64 tsf; - u8 rssi; - u8 agc; - u16 sig_avg; - u16 noise_diff; - struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); - struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); - struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - u8 *data = IWL_RX_DATA(pkt); - - /* MAC header */ - fc = le16_to_cpu(header->frame_control); - seq_ctl = le16_to_cpu(header->seq_ctrl); - - /* metadata */ - channel = le16_to_cpu(rx_hdr->channel); - phy_flags = le16_to_cpu(rx_hdr->phy_flags); - rate_sym = rx_hdr->rate; - length = le16_to_cpu(rx_hdr->len); - - /* end-of-frame status and timestamp */ - status = le32_to_cpu(rx_end->status); - bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); - tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; - tsf = le64_to_cpu(rx_end->timestamp); - - /* signal statistics */ - rssi = rx_stats->rssi; - agc = rx_stats->agc; - sig_avg = le16_to_cpu(rx_stats->sig_avg); - noise_diff = le16_to_cpu(rx_stats->noise_diff); - - to_us = !compare_ether_addr(header->addr1, priv->mac_addr); - - /* if data frame is to us and all is good, - * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == - (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { - dataframe = 1; - if (!group100) - print_summary = 1; /* print each frame */ - else if (priv->framecnt_to_us < 100) { - priv->framecnt_to_us++; - print_summary = 0; - } else { - priv->framecnt_to_us = 0; - print_summary = 1; - hundred = 1; - } - } else { - /* print summary for all other frames */ - print_summary = 1; - } - - if (print_summary) { - char *title; - u32 rate; - - if (hundred) - title = "100Frames"; - else if (fc & IEEE80211_FCTL_RETRY) - title = "Retry"; - else if (ieee80211_is_assoc_response(fc)) - title = "AscRsp"; - else if (ieee80211_is_reassoc_response(fc)) - title = "RasRsp"; - else if (ieee80211_is_probe_response(fc)) { - title = "PrbRsp"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_beacon(fc)) { - title = "Beacon"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_atim(fc)) - title = "ATIM"; - else if (ieee80211_is_auth(fc)) - title = "Auth"; - else if (ieee80211_is_deauth(fc)) - title = "DeAuth"; - else if (ieee80211_is_disassoc(fc)) - title = "DisAssoc"; - else - title = "Frame"; - - rate = iwl3945_rate_index_from_plcp(rate_sym); - if (rate == -1) - rate = 0; - else - rate = iwl3945_rates[rate].ieee / 2; - - /* print frame summary. - * MAC addresses show just the last byte (for brevity), - * but you can hack it to show more, if you'd like to. */ - if (dataframe) - IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%u, \n", - title, fc, header->addr1[5], - length, rssi, channel, rate); - else { - /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " - "src=0x%02x, rssi=%u, tim=%lu usec, " - "phy=0x%02x, chnl=%d\n", - title, fc, header->addr1[5], - header->addr3[5], rssi, - tsf_low - priv->scan_start_tsf, - phy_flags, channel); - } - } - if (print_dump) - iwl3945_print_hex_dump(IWL_DL_RX, data, length); -} -#endif - static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv) { if (priv->hw_setting.shared_virt) @@ -1915,7 +1731,6 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv, /* * QoS support */ -#ifdef CONFIG_IWL3945_QOS static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv, struct iwl3945_qosparam_cmd *qos) { @@ -2044,7 +1859,6 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force) } } -#endif /* CONFIG_IWL3945_QOS */ /* * Power management (not Tx power!) functions */ @@ -2244,39 +2058,13 @@ int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *h 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; } -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x - -static const char *iwl3945_get_tx_fail_reason(u32 status) -{ - switch (status & TX_STATUS_MSK) { - case TX_STATUS_SUCCESS: - return "SUCCESS"; - TX_STATUS_ENTRY(SHORT_LIMIT); - TX_STATUS_ENTRY(LONG_LIMIT); - TX_STATUS_ENTRY(FIFO_UNDERRUN); - TX_STATUS_ENTRY(MGMNT_ABORT); - TX_STATUS_ENTRY(NEXT_FRAG); - TX_STATUS_ENTRY(LIFE_EXPIRE); - TX_STATUS_ENTRY(DEST_PS); - TX_STATUS_ENTRY(ABORTED); - TX_STATUS_ENTRY(BT_RETRY); - TX_STATUS_ENTRY(STA_INVALID); - TX_STATUS_ENTRY(FRAG_DROPPED); - TX_STATUS_ENTRY(TID_DISABLE); - TX_STATUS_ENTRY(FRAME_FLUSHED); - TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); - TX_STATUS_ENTRY(TX_LOCKED); - TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); - } - - return "UNKNOWN"; -} - /** * iwl3945_scan_cancel - Cancel any currently executing HW scan * @@ -2461,9 +2249,10 @@ static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt) return 0; } -static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode) +static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) { + if (band == IEEE80211_BAND_5GHZ) { priv->staging_rxon.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); @@ -2515,6 +2304,9 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; + default: + IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode); + break; } #if 0 @@ -2526,7 +2318,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif - ch_info = iwl3945_get_channel_info(priv, priv->phymode, + ch_info = iwl3945_get_channel_info(priv, priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info) @@ -2542,11 +2334,11 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); if (is_channel_a_band(ch_info)) - priv->phymode = MODE_IEEE80211A; + priv->band = IEEE80211_BAND_5GHZ; else - priv->phymode = MODE_IEEE80211G; + priv->band = IEEE80211_BAND_2GHZ; - iwl3945_set_flags_for_phymode(priv, priv->phymode); + iwl3945_set_flags_for_phymode(priv, priv->band); priv->staging_rxon.ofdm_basic_rates = (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; @@ -2560,7 +2352,7 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) const struct iwl3945_channel_info *ch_info; ch_info = iwl3945_get_channel_info(priv, - priv->phymode, + priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info || !is_channel_ibss(ch_info)) { @@ -2694,8 +2486,12 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3); else cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2); - } else + } else { cmd->cmd.tx.timeout.pm_frame_timeout = 0; +#ifdef CONFIG_IWL3945_LEDS + priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len); +#endif + } cmd->cmd.tx.driver_txop = 0; cmd->cmd.tx.tx_flags = tx_flags; @@ -2792,7 +2588,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, goto drop_unlock; } - if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) { + if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) { IWL_ERROR("ERROR: No TX rate available.\n"); goto drop_unlock; } @@ -2963,7 +2759,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, ieee80211_get_hdrlen(fc)); /* Tell device the write index *just past* this latest filled TFD */ - q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd); + q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); rc = iwl3945_tx_queue_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); @@ -2992,12 +2788,12 @@ drop: static void iwl3945_set_rate(struct iwl3945_priv *priv) { - const struct ieee80211_hw_mode *hw = NULL; + const struct ieee80211_supported_band *sband = NULL; struct ieee80211_rate *rate; int i; - hw = iwl3945_get_hw_mode(priv, priv->phymode); - if (!hw) { + sband = iwl3945_get_band(priv, priv->band); + if (!sband) { IWL_ERROR("Failed to set rate: unable to get hw mode\n"); return; } @@ -3005,24 +2801,17 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv) priv->active_rate = 0; priv->active_rate_basic = 0; - IWL_DEBUG_RATE("Setting rates for 802.11%c\n", - hw->mode == MODE_IEEE80211A ? - 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g')); - - for (i = 0; i < hw->num_rates; i++) { - rate = &(hw->rates[i]); - if ((rate->val < IWL_RATE_COUNT) && - (rate->flags & IEEE80211_RATE_SUPPORTED)) { - IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n", - rate->val, iwl3945_rates[rate->val].plcp, - (rate->flags & IEEE80211_RATE_BASIC) ? - "*" : ""); - priv->active_rate |= (1 << rate->val); - if (rate->flags & IEEE80211_RATE_BASIC) - priv->active_rate_basic |= (1 << rate->val); - } else - IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n", - rate->val, iwl3945_rates[rate->val].plcp); + IWL_DEBUG_RATE("Setting rates for %s GHz\n", + sband->band == IEEE80211_BAND_2GHZ ? "2.4" : "5"); + + for (i = 0; i < sband->n_bitrates; i++) { + rate = &sband->bitrates[i]; + if ((rate->hw_value < IWL_RATE_COUNT) && + !(rate->flags & IEEE80211_CHAN_DISABLED)) { + IWL_DEBUG_RATE("Adding rate index %d (plcp %d)\n", + rate->hw_value, iwl3945_rates[rate->hw_value].plcp); + priv->active_rate |= (1 << rate->hw_value); + } } IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n", @@ -3330,127 +3119,6 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, } #endif -static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv, - struct iwl3945_tx_info *tx_sta) -{ - - tx_sta->status.ack_signal = 0; - tx_sta->status.excessive_retries = 0; - tx_sta->status.queue_length = 0; - tx_sta->status.queue_number = 0; - - if (in_interrupt()) - ieee80211_tx_status_irqsafe(priv->hw, - tx_sta->skb[0], &(tx_sta->status)); - else - ieee80211_tx_status(priv->hw, - tx_sta->skb[0], &(tx_sta->status)); - - tx_sta->skb[0] = NULL; -} - -/** - * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd - * - * When FW advances 'R' index, all entries between old and new 'R' index - * need to be reclaimed. As result, some free space forms. If there is - * enough free space (> low mark), wake the stack that feeds us. - */ -static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index) -{ - struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; - struct iwl3945_queue *q = &txq->q; - int nfreed = 0; - - if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " - "is out of range [0-%d] %d %d.\n", txq_id, - index, q->n_bd, q->write_ptr, q->read_ptr); - return 0; - } - - for (index = iwl3945_queue_inc_wrap(index, q->n_bd); - q->read_ptr != index; - q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) { - if (txq_id != IWL_CMD_QUEUE_NUM) { - iwl3945_txstatus_to_ieee(priv, - &(txq->txb[txq->q.read_ptr])); - iwl3945_hw_txq_free_tfd(priv, txq); - } else if (nfreed > 1) { - IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, - q->write_ptr, q->read_ptr); - queue_work(priv->workqueue, &priv->restart); - } - nfreed++; - } - - if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) && - (txq_id != IWL_CMD_QUEUE_NUM) && - priv->mac80211_registered) - ieee80211_wake_queue(priv->hw, txq_id); - - - return nfreed; -} - -static int iwl3945_is_tx_success(u32 status) -{ - return (status & 0xFF) == 0x1; -} - -/****************************************************************************** - * - * Generic RX handler implementations - * - ******************************************************************************/ -/** - * iwl3945_rx_reply_tx - Handle Tx response - */ -static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) -{ - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int index = SEQ_TO_INDEX(sequence); - struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; - struct ieee80211_tx_status *tx_status; - struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le32_to_cpu(tx_resp->status); - - if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " - "is out of range [0-%d] %d %d\n", txq_id, - index, txq->q.n_bd, txq->q.write_ptr, - txq->q.read_ptr); - return; - } - - tx_status = &(txq->txb[txq->q.read_ptr].status); - - tx_status->retry_count = tx_resp->failure_frame; - tx_status->queue_number = status; - tx_status->queue_length = tx_resp->bt_kill_count; - tx_status->queue_length |= tx_resp->failure_rts; - - tx_status->flags = - iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; - - tx_status->control.tx_rate = iwl3945_rate_index_from_plcp(tx_resp->rate); - - IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", - txq_id, iwl3945_get_tx_fail_reason(status), status, - tx_resp->rate, tx_resp->failure_frame); - - IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); - if (index != -1) - iwl3945_tx_queue_reclaim(priv, txq_id, index); - - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); -} - - static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { @@ -3797,13 +3465,44 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv) priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = iwl3945_rx_scan_complete_notif; priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; - priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx; /* Set up hardware specific Rx handlers */ iwl3945_hw_rx_handler_setup(priv); } /** + * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries + * When FW advances 'R' index, all entries between old and new 'R' index + * need to be reclaimed. + */ +static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv, + int txq_id, int index) +{ + struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; + struct iwl3945_queue *q = &txq->q; + int nfreed = 0; + + if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) { + IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " + "is out of range [0-%d] %d %d.\n", txq_id, + index, q->n_bd, q->write_ptr, q->read_ptr); + return; + } + + for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { + if (nfreed > 1) { + IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, + q->write_ptr, q->read_ptr); + queue_work(priv->workqueue, &priv->restart); + break; + } + nfreed++; + } +} + + +/** * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them * @rxb: Rx buffer to reclaim * @@ -3822,12 +3521,6 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, int cmd_index; struct iwl3945_cmd *cmd; - /* If a Tx command is being handled and it isn't in the actual - * command queue then there a command routing bug has been introduced - * in the queue management code. */ - if (txq_id != IWL_CMD_QUEUE_NUM) - IWL_ERROR("Error wrong command queue %d command id 0x%X\n", - txq_id, pkt->hdr.cmd); BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); @@ -3841,7 +3534,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, !cmd->meta.u.callback(priv, cmd, rxb->skb)) rxb->skb = NULL; - iwl3945_tx_queue_reclaim(priv, txq_id, index); + iwl3945_cmd_queue_reclaim(priv, txq_id, index); if (!(cmd->meta.flags & CMD_ASYNC)) { clear_bit(STATUS_HCMD_ACTIVE, &priv->status); @@ -4460,6 +4153,16 @@ static void iwl3945_enable_interrupts(struct iwl3945_priv *priv) iwl3945_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); } + +/* call this function to flush any scheduled tasklet */ +static inline void iwl_synchronize_irq(struct iwl3945_priv *priv) +{ + /* wait to make sure we flush pedding tasklet*/ + synchronize_irq(priv->pci_dev->irq); + tasklet_kill(&priv->irq_tasklet); +} + + static inline void iwl3945_disable_interrupts(struct iwl3945_priv *priv) { clear_bit(STATUS_INT_ENABLED, &priv->status); @@ -4521,8 +4224,7 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv) if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { IWL_ERROR("Start IWL Error Log Dump:\n"); - IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n", - priv->status, priv->config, count); + IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count); } IWL_ERROR("Desc Time asrtPC blink2 " @@ -4742,9 +4444,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) * atomic, make sure that inta covers all the interrupts that * we've discovered, even if FH interrupt came in just after * reading CSR_INT. */ - if (inta_fh & CSR_FH_INT_RX_MASK) + if (inta_fh & CSR39_FH_INT_RX_MASK) inta |= CSR_INT_BIT_FH_RX; - if (inta_fh & CSR_FH_INT_TX_MASK) + if (inta_fh & CSR39_FH_INT_TX_MASK) inta |= CSR_INT_BIT_FH_TX; /* Now service all interrupt bits discovered above. */ @@ -4792,7 +4494,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) /* Queue restart only if RF_KILL switch was set to "kill" * when we loaded driver, and is now set to "enable". * After we're Alive, RF_KILL gets handled by - * iwl_rx_card_state_notif() */ + * iwl3945_rx_card_state_notif() */ if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) { clear_bit(STATUS_RF_KILL_HW, &priv->status); queue_work(priv->workqueue, &priv->restart); @@ -4860,7 +4562,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) } /* Re-enable all interrupts */ - iwl3945_enable_interrupts(priv); + /* only Re-enable if disabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl3945_enable_interrupts(priv); #ifdef CONFIG_IWL3945_DEBUG if (iwl3945_debug_level & (IWL_DL_ISR)) { @@ -4924,7 +4628,9 @@ unplugged: none: /* re-enable interrupts here since we don't have anything to service. */ - iwl3945_enable_interrupts(priv); + /* only Re-enable if disabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl3945_enable_interrupts(priv); spin_unlock(&priv->lock); return IRQ_NONE; } @@ -5026,24 +4732,24 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban * Based on band and channel number. */ const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv, - int phymode, u16 channel) + enum ieee80211_band band, u16 channel) { int i; - switch (phymode) { - case MODE_IEEE80211A: + switch (band) { + case IEEE80211_BAND_5GHZ: for (i = 14; i < priv->channel_count; i++) { if (priv->channel_info[i].channel == channel) return &priv->channel_info[i]; } break; - case MODE_IEEE80211B: - case MODE_IEEE80211G: + case IEEE80211_BAND_2GHZ: if (channel >= 1 && channel <= 14) return &priv->channel_info[channel - 1]; break; - + case IEEE80211_NUM_BANDS: + WARN_ON(1); } return NULL; @@ -5106,8 +4812,8 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) /* Loop through each band adding each of the channels */ for (ch = 0; ch < eeprom_ch_count; ch++) { ch_info->channel = eeprom_ch_index[ch]; - ch_info->phymode = (band == 1) ? MODE_IEEE80211B : - MODE_IEEE80211A; + ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : + IEEE80211_BAND_5GHZ; /* permanently store EEPROM's channel regulatory flags * and max power in channel info database. */ @@ -5134,11 +4840,12 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; ch_info->min_power = 0; - IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" + IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x" " %ddBm): Ad-Hoc %ssupported\n", ch_info->channel, is_channel_a_band(ch_info) ? "5.2" : "2.4", + CHECK_AND_PRINT(VALID), CHECK_AND_PRINT(IBSS), CHECK_AND_PRINT(ACTIVE), CHECK_AND_PRINT(RADAR), @@ -5203,18 +4910,20 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv) #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 -static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, int phymode) +static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) return IWL_ACTIVE_DWELL_TIME_52; else return IWL_ACTIVE_DWELL_TIME_24; } -static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode) +static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, + enum ieee80211_band band) { - u16 active = iwl3945_get_active_dwell_time(priv, phymode); - u16 passive = (phymode != MODE_IEEE80211A) ? + u16 active = iwl3945_get_active_dwell_time(priv, band); + u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -5234,28 +4943,32 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode return passive; } -static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, +static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, + enum ieee80211_band band, u8 is_active, u8 direct_mask, struct iwl3945_scan_channel *scan_ch) { const struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode; + const struct ieee80211_supported_band *sband; const struct iwl3945_channel_info *ch_info; u16 passive_dwell = 0; u16 active_dwell = 0; int added, i; - hw_mode = iwl3945_get_hw_mode(priv, phymode); - if (!hw_mode) + sband = iwl3945_get_band(priv, band); + if (!sband) return 0; - channels = hw_mode->channels; + channels = sband->channels; - active_dwell = iwl3945_get_active_dwell_time(priv, phymode); - passive_dwell = iwl3945_get_passive_dwell_time(priv, phymode); + active_dwell = iwl3945_get_active_dwell_time(priv, band); + passive_dwell = iwl3945_get_passive_dwell_time(priv, band); + + for (i = 0, added = 0; i < sband->n_channels; i++) { + if (channels[i].flags & IEEE80211_CHAN_DISABLED) + continue; - for (i = 0, added = 0; i < hw_mode->num_channels; i++) { - if (channels[i].chan == + if (channels[i].hw_value == le16_to_cpu(priv->active_rxon.channel)) { if (iwl3945_is_associated(priv)) { IWL_DEBUG_SCAN @@ -5266,9 +4979,9 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, } else if (priv->only_active_channel) continue; - scan_ch->channel = channels[i].chan; + scan_ch->channel = channels[i].hw_value; - ch_info = iwl3945_get_channel_info(priv, phymode, scan_ch->channel); + ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", scan_ch->channel); @@ -5276,7 +4989,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, } if (!is_active || is_channel_passive(ch_info) || - !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN)) + (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) scan_ch->type = 0; /* passive */ else scan_ch->type = 1; /* active */ @@ -5295,7 +5008,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, /* scan_pwr_info->tpc.dsp_atten; */ /*scan_pwr_info->tpc.tx_gain; */ - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; else { scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); @@ -5319,41 +5032,23 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, return added; } -static void iwl3945_reset_channel_flag(struct iwl3945_priv *priv) -{ - int i, j; - for (i = 0; i < 3; i++) { - struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i]; - for (j = 0; j < hw_mode->num_channels; j++) - hw_mode->channels[j].flag = hw_mode->channels[j].val; - } -} - static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, struct ieee80211_rate *rates) { int i; for (i = 0; i < IWL_RATE_COUNT; i++) { - rates[i].rate = iwl3945_rates[i].ieee * 5; - rates[i].val = i; /* Rate scaling will work on indexes */ - rates[i].val2 = i; - rates[i].flags = IEEE80211_RATE_SUPPORTED; - /* Only OFDM have the bits-per-symbol set */ - if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE)) - rates[i].flags |= IEEE80211_RATE_OFDM; - else { + rates[i].bitrate = iwl3945_rates[i].ieee * 5; + rates[i].hw_value = i; /* Rate scaling will work on indexes */ + rates[i].hw_value_short = i; + rates[i].flags = 0; + if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) { /* - * If CCK 1M then set rate flag to CCK else CCK_2 - * which is CCK | PREAMBLE2 + * If CCK != 1M then set short preamble rate flag. */ rates[i].flags |= (iwl3945_rates[i].plcp == 10) ? - IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2; + 0 : IEEE80211_RATE_SHORT_PREAMBLE; } - - /* Set up which ones are basic rates... */ - if (IWL_BASIC_RATES_MASK & (1 << i)) - rates[i].flags |= IEEE80211_RATE_BASIC; } } @@ -5363,143 +5058,117 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, static int iwl3945_init_geos(struct iwl3945_priv *priv) { struct iwl3945_channel_info *ch; - struct ieee80211_hw_mode *modes; + struct ieee80211_supported_band *sband; struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; struct ieee80211_rate *rates; int i = 0; - enum { - A = 0, - B = 1, - G = 2, - }; - int mode_count = 3; - if (priv->modes) { + if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || + priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { IWL_DEBUG_INFO("Geography modes already initialized.\n"); set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } - modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count, - GFP_KERNEL); - if (!modes) - return -ENOMEM; - channels = kzalloc(sizeof(struct ieee80211_channel) * priv->channel_count, GFP_KERNEL); - if (!channels) { - kfree(modes); + if (!channels) return -ENOMEM; - } - rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)), + rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)), GFP_KERNEL); if (!rates) { - kfree(modes); kfree(channels); return -ENOMEM; } - /* 0 = 802.11a - * 1 = 802.11b - * 2 = 802.11g - */ - /* 5.2GHz channels start after the 2.4GHz channels */ - modes[A].mode = MODE_IEEE80211A; - modes[A].channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; - modes[A].rates = &rates[4]; - modes[A].num_rates = 8; /* just OFDM */ - modes[A].num_channels = 0; - - modes[B].mode = MODE_IEEE80211B; - modes[B].channels = channels; - modes[B].rates = rates; - modes[B].num_rates = 4; /* just CCK */ - modes[B].num_channels = 0; - - modes[G].mode = MODE_IEEE80211G; - modes[G].channels = channels; - modes[G].rates = rates; - modes[G].num_rates = 12; /* OFDM & CCK */ - modes[G].num_channels = 0; + sband = &priv->bands[IEEE80211_BAND_5GHZ]; + sband->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; + /* just OFDM */ + sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; + sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; + + sband = &priv->bands[IEEE80211_BAND_2GHZ]; + sband->channels = channels; + /* OFDM & CCK */ + sband->bitrates = rates; + sband->n_bitrates = IWL_RATE_COUNT; priv->ieee_channels = channels; priv->ieee_rates = rates; iwl3945_init_hw_rates(priv, rates); - for (i = 0, geo_ch = channels; i < priv->channel_count; i++) { + for (i = 0; i < priv->channel_count; i++) { ch = &priv->channel_info[i]; - if (!is_channel_valid(ch)) { - IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- " - "skipping.\n", - ch->channel, is_channel_a_band(ch) ? - "5.2" : "2.4"); + /* FIXME: might be removed if scan is OK*/ + if (!is_channel_valid(ch)) continue; - } if (is_channel_a_band(ch)) - geo_ch = &modes[A].channels[modes[A].num_channels++]; - else { - geo_ch = &modes[B].channels[modes[B].num_channels++]; - modes[G].num_channels++; - } + sband = &priv->bands[IEEE80211_BAND_5GHZ]; + else + sband = &priv->bands[IEEE80211_BAND_2GHZ]; + + geo_ch = &sband->channels[sband->n_channels++]; - geo_ch->freq = ieee80211chan2mhz(ch->channel); - geo_ch->chan = ch->channel; - geo_ch->power_level = ch->max_power_avg; - geo_ch->antenna_max = 0xff; + geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel); + geo_ch->max_power = ch->max_power_avg; + geo_ch->max_antenna_gain = 0xff; + geo_ch->hw_value = ch->channel; if (is_channel_valid(ch)) { - geo_ch->flag = IEEE80211_CHAN_W_SCAN; - if (ch->flags & EEPROM_CHANNEL_IBSS) - geo_ch->flag |= IEEE80211_CHAN_W_IBSS; + if (!(ch->flags & EEPROM_CHANNEL_IBSS)) + geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; - if (ch->flags & EEPROM_CHANNEL_ACTIVE) - geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN; + if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) + geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; if (ch->flags & EEPROM_CHANNEL_RADAR) - geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT; + geo_ch->flags |= IEEE80211_CHAN_RADAR; if (ch->max_power_avg > priv->max_channel_txpower_limit) priv->max_channel_txpower_limit = ch->max_power_avg; + } else { + geo_ch->flags |= IEEE80211_CHAN_DISABLED; } - geo_ch->val = geo_ch->flag; + /* Save flags for reg domain usage */ + geo_ch->orig_flags = geo_ch->flags; + + IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n", + ch->channel, geo_ch->center_freq, + is_channel_a_band(ch) ? "5.2" : "2.4", + geo_ch->flags & IEEE80211_CHAN_DISABLED ? + "restricted" : "valid", + geo_ch->flags); } - if ((modes[A].num_channels == 0) && priv->is_abg) { + if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && + priv->cfg->sku & IWL_SKU_A) { printk(KERN_INFO DRV_NAME ": Incorrectly detected BG card as ABG. Please send " "your PCI ID 0x%04X:0x%04X to maintainer.\n", priv->pci_dev->device, priv->pci_dev->subsystem_device); - priv->is_abg = 0; + priv->cfg->sku &= ~IWL_SKU_A; } printk(KERN_INFO DRV_NAME ": Tunable channels: %d 802.11bg, %d 802.11a channels\n", - modes[G].num_channels, modes[A].num_channels); - - /* - * NOTE: We register these in preference of order -- the - * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick - * a phymode based on rates or AP capabilities but seems to - * configure it purely on if the channel being configured - * is supported by a mode -- and the first match is taken - */ + priv->bands[IEEE80211_BAND_2GHZ].n_channels, + priv->bands[IEEE80211_BAND_5GHZ].n_channels); - if (modes[G].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[G]); - if (modes[B].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[B]); - if (modes[A].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[A]); + if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) + priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &priv->bands[IEEE80211_BAND_2GHZ]; + if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) + priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + &priv->bands[IEEE80211_BAND_5GHZ]; - priv->modes = modes; set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; @@ -5510,7 +5179,6 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) */ static void iwl3945_free_geos(struct iwl3945_priv *priv) { - kfree(priv->modes); kfree(priv->ieee_channels); kfree(priv->ieee_rates); clear_bit(STATUS_GEO_CONFIGURED, &priv->status); @@ -5837,7 +5505,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) int ret = 0; const struct firmware *ucode_raw; /* firmware file name contains uCode/driver compatibility version */ - const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode"; + const char *name = priv->cfg->fw_name; u8 *src; size_t len; u32 ver, inst_size, data_size, init_size, init_data_size, boot_size; @@ -6209,6 +5877,8 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) iwl3945_reg_txpower_periodic(priv); + iwl3945_led_register(priv); + IWL_DEBUG_INFO("ALIVE processing complete.\n"); set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); @@ -6216,6 +5886,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) if (priv->error_recovering) iwl3945_error_recovery(priv); + ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); return; restart: @@ -6237,6 +5908,7 @@ static void __iwl3945_down(struct iwl3945_priv *priv) if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); + iwl3945_led_unregister(priv); iwl3945_clear_stations_table(priv); /* Unblock any waiting calls */ @@ -6251,7 +5923,10 @@ static void __iwl3945_down(struct iwl3945_priv *priv) iwl3945_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ + spin_lock_irqsave(&priv->lock, flags); iwl3945_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + iwl_synchronize_irq(priv); if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); @@ -6519,7 +6194,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) struct iwl3945_scan_cmd *scan; struct ieee80211_conf *conf = NULL; u8 direct_mask; - int phymode; + enum ieee80211_band band; conf = ieee80211_get_hw_conf(priv->hw); @@ -6651,13 +6326,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; scan->tx_cmd.rate = IWL_RATE_1M_PLCP; scan->good_CRC_th = 0; - phymode = MODE_IEEE80211G; + band = IEEE80211_BAND_2GHZ; break; case 1: scan->tx_cmd.rate = IWL_RATE_6M_PLCP; scan->good_CRC_th = IWL_GOOD_CRC_TH; - phymode = MODE_IEEE80211A; + band = IEEE80211_BAND_5GHZ; break; default: @@ -6671,18 +6346,23 @@ static void iwl3945_bg_request_scan(struct work_struct *data) if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) scan->filter_flags = RXON_FILTER_PROMISC_MSK; - if (direct_mask) + if (direct_mask) { IWL_DEBUG_SCAN ("Initiating direct scan for %s.\n", iwl3945_escape_essid(priv->essid, priv->essid_len)); - else + scan->channel_count = + iwl3945_get_channels_for_scan( + priv, band, 1, /* active */ + direct_mask, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + } else { IWL_DEBUG_SCAN("Initiating indirect scan.\n"); - - scan->channel_count = - iwl3945_get_channels_for_scan( - priv, phymode, 1, /* active */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + scan->channel_count = + iwl3945_get_channels_for_scan( + priv, band, 0, /* passive */ + direct_mask, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + } cmd.len += le16_to_cpu(scan->tx_cmd.len) + scan->channel_count * sizeof(struct iwl3945_scan_channel); @@ -6825,7 +6505,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data) iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0); iwl3945_add_station(priv, priv->bssid, 0, 0); iwl3945_sync_sta(priv, IWL_STA_ID, - (priv->phymode == MODE_IEEE80211A)? + (priv->band == IEEE80211_BAND_5GHZ) ? IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, CMD_ASYNC); iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); @@ -6841,9 +6521,8 @@ static void iwl3945_bg_post_associate(struct work_struct *data) iwl3945_sequence_reset(priv); -#ifdef CONFIG_IWL3945_QOS iwl3945_activate_qos(priv, 0); -#endif /* CONFIG_IWL3945_QOS */ + /* we have just associated, don't start scan too early */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; mutex_unlock(&priv->mutex); @@ -7020,7 +6699,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, } IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, - ctl->tx_rate); + ctl->tx_rate->bitrate); if (iwl3945_tx_skb(priv, skb, ctl)) dev_kfree_skb_any(skb); @@ -7079,7 +6758,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co int ret = 0; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); + IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); @@ -7099,19 +6778,20 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co spin_lock_irqsave(&priv->lock, flags); - ch_info = iwl3945_get_channel_info(priv, conf->phymode, conf->channel); + ch_info = iwl3945_get_channel_info(priv, conf->channel->band, + conf->channel->hw_value); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n", - conf->channel, conf->phymode); + conf->channel->hw_value, conf->channel->band); IWL_DEBUG_MAC80211("leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); ret = -EINVAL; goto out; } - iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel); + iwl3945_set_rxon_channel(priv, conf->channel->band, conf->channel->hw_value); - iwl3945_set_flags_for_phymode(priv, conf->phymode); + iwl3945_set_flags_for_phymode(priv, conf->channel->band); /* The list of supported rates and rate mask can be different * for each phymode; since the phymode may have changed, reset @@ -7225,6 +6905,12 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (conf == NULL) return -EIO; + if (priv->vif != vif) { + IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); + mutex_unlock(&priv->mutex); + return 0; + } + /* XXX: this MUST use conf->mac_addr */ if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && @@ -7249,17 +6935,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { */ - if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211("leave - scanning\n"); - mutex_unlock(&priv->mutex); - return 0; - } - - if (priv->vif != vif) { - IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); - mutex_unlock(&priv->mutex); - return 0; - } if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { if (!conf->bssid) { @@ -7487,10 +7162,8 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, const struct ieee80211_tx_queue_params *params) { struct iwl3945_priv *priv = hw->priv; -#ifdef CONFIG_IWL3945_QOS unsigned long flags; int q; -#endif /* CONFIG_IWL3945_QOS */ IWL_DEBUG_MAC80211("enter\n"); @@ -7504,7 +7177,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, return 0; } -#ifdef CONFIG_IWL3945_QOS if (!priv->qos_data.qos_enable) { priv->qos_data.qos_active = 0; IWL_DEBUG_MAC80211("leave - qos not enabled\n"); @@ -7518,7 +7190,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; priv->qos_data.def_qos_parm.ac[q].edca_txop = - cpu_to_le16((params->burst_time * 100)); + cpu_to_le16((params->txop * 32)); priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; priv->qos_data.qos_active = 1; @@ -7533,8 +7205,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, mutex_unlock(&priv->mutex); -#endif /*CONFIG_IWL3945_QOS */ - IWL_DEBUG_MAC80211("leave\n"); return 0; } @@ -7599,9 +7269,8 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter\n"); -#ifdef CONFIG_IWL3945_QOS iwl3945_reset_qos(priv); -#endif + cancel_delayed_work(&priv->post_associate); spin_lock_irqsave(&priv->lock, flags); @@ -7689,9 +7358,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk IWL_DEBUG_MAC80211("leave\n"); spin_unlock_irqrestore(&priv->lock, flags); -#ifdef CONFIG_IWL3945_QOS iwl3945_reset_qos(priv); -#endif queue_work(priv->workqueue, &priv->post_associate.work); @@ -7892,65 +7559,6 @@ static ssize_t store_filter_flags(struct device *d, static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, store_filter_flags); -static ssize_t show_tune(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; - - return sprintf(buf, "0x%04X\n", - (priv->phymode << 8) | - le16_to_cpu(priv->active_rxon.channel)); -} - -static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode); - -static ssize_t store_tune(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; - char *p = (char *)buf; - u16 tune = simple_strtoul(p, &p, 0); - u8 phymode = (tune >> 8) & 0xff; - u16 channel = tune & 0xff; - - IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel); - - mutex_lock(&priv->mutex); - if ((le16_to_cpu(priv->staging_rxon.channel) != channel) || - (priv->phymode != phymode)) { - const struct iwl3945_channel_info *ch_info; - - ch_info = iwl3945_get_channel_info(priv, phymode, channel); - if (!ch_info) { - IWL_WARNING("Requested invalid phymode/channel " - "combination: %d %d\n", phymode, channel); - mutex_unlock(&priv->mutex); - return -EINVAL; - } - - /* Cancel any currently running scans... */ - if (iwl3945_scan_cancel_timeout(priv, 100)) - IWL_WARNING("Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO("Committing phymode and " - "rxon.channel = %d %d\n", - phymode, channel); - - iwl3945_set_rxon_channel(priv, phymode, channel); - iwl3945_set_flags_for_phymode(priv, phymode); - - iwl3945_set_rate(priv); - iwl3945_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune); - #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT static ssize_t show_measurement(struct device *d, @@ -8024,31 +7632,6 @@ static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, show_measurement, store_measurement); #endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */ -static ssize_t show_rate(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl3945_priv *priv = dev_get_drvdata(d); - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->sta_lock, flags); - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) - i = priv->stations[IWL_AP_ID].current_rate.s.rate; - else - i = priv->stations[IWL_STA_ID].current_rate.s.rate; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - i = iwl3945_rate_index_from_plcp(i); - if (i == -1) - return sprintf(buf, "0\n"); - - return sprintf(buf, "%d%s\n", - (iwl3945_rates[i].ieee >> 1), - (iwl3945_rates[i].ieee & 0x1) ? ".5" : ""); -} - -static DEVICE_ATTR(rate, S_IRUSR, show_rate, NULL); - static ssize_t store_retry_rate(struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -8165,73 +7748,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, static ssize_t show_channels(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = dev_get_drvdata(d); - int len = 0, i; - struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode = NULL; - int count = 0; - - if (!iwl3945_is_ready(priv)) - return -EAGAIN; - - hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211G); - if (!hw_mode) - hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211B); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } - - len += - sprintf(&buf[len], - "Displaying %d channels in 2.4GHz band " - "(802.11bg):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211A); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } else { - channels = NULL; - count = 0; - } - - len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band " - "(802.11a):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - return len; + /* all this shit doesn't belong into sysfs anyway */ + return 0; } static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); @@ -8404,14 +7922,12 @@ static struct attribute *iwl3945_sysfs_entries[] = { &dev_attr_measurement.attr, #endif &dev_attr_power_level.attr, - &dev_attr_rate.attr, &dev_attr_retry_rate.attr, &dev_attr_rf_kill.attr, &dev_attr_rs_window.attr, &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, - &dev_attr_tune.attr, &dev_attr_tx_power.attr, NULL @@ -8444,10 +7960,11 @@ static struct ieee80211_ops iwl3945_hw_ops = { static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0; - u32 pci_id; 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); /* Disabling hardware scan means that mac80211 will perform scans @@ -8457,10 +7974,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl3945_hw_ops.hw_scan = NULL; } - if ((iwl3945_param_queues_num > IWL_MAX_NUM_QUEUES) || + if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) || (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); + IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); err = -EINVAL; goto out; } @@ -8482,6 +7999,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->hw = hw; priv->pci_dev = pdev; + priv->cfg = cfg; /* Select antenna (may be helpful if only one antenna is connected) */ priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna; @@ -8532,7 +8050,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->data_retry_limit = -1; priv->ieee_channels = NULL; priv->ieee_rates = NULL; - priv->phymode = -1; + priv->band = IEEE80211_BAND_2GHZ; err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (!err) @@ -8571,32 +8089,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->iw_mode = IEEE80211_IF_TYPE_STA; - pci_id = - (priv->pci_dev->device << 16) | priv->pci_dev->subsystem_device; - - switch (pci_id) { - case 0x42221005: /* 0x4222 0x8086 0x1005 is BG SKU */ - case 0x42221034: /* 0x4222 0x8086 0x1034 is BG SKU */ - case 0x42271014: /* 0x4227 0x8086 0x1014 is BG SKU */ - case 0x42221044: /* 0x4222 0x8086 0x1044 is BG SKU */ - priv->is_abg = 0; - break; - - /* - * Rest are assumed ABG SKU -- if this is not the - * case then the card will get the wrong 'Detected' - * line in the kernel log however the code that - * initializes the GEO table will detect no A-band - * channels and remove the is_abg mask. - */ - default: - priv->is_abg = 1; - break; - } - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 3945%sBG Network Connection\n", - priv->is_abg ? "A" : ""); + ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); /* Device-specific setup */ if (iwl3945_hw_set_hw_setting(priv)) { @@ -8604,7 +8098,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out_iounmap; } -#ifdef CONFIG_IWL3945_QOS if (iwl3945_param_qos_enable) priv->qos_data.qos_enable = 1; @@ -8612,9 +8105,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->qos_data.qos_active = 0; priv->qos_data.qos_cap.val = 0; -#endif /* CONFIG_IWL3945_QOS */ - iwl3945_set_rxon_channel(priv, MODE_IEEE80211G, 6); + iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); iwl3945_setup_deferred_work(priv); iwl3945_setup_rx_handlers(priv); @@ -8623,7 +8115,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->power_mode = IWL_POWER_AC; priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; + spin_lock_irqsave(&priv->lock, flags); iwl3945_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); if (err) { @@ -8665,9 +8159,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_ERROR("initializing geos failed: %d\n", err); goto out_free_channel_map; } - iwl3945_reset_channel_flag(priv); - iwl3945_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); if (err) { IWL_ERROR("Failed to register network device (error %d)\n", err); @@ -8711,6 +8203,7 @@ 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) return; @@ -8721,6 +8214,15 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_down(priv); + /* make sure we flush any pending irq or + * tasklet for the driver + */ + spin_lock_irqsave(&priv->lock, flags); + iwl3945_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + 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]) { @@ -8742,7 +8244,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); - iwl3945_rate_control_unregister(priv->hw); } /*netif_stop_queue(dev); */ @@ -8823,21 +8324,35 @@ static int __init iwl3945_init(void) int ret; printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + + ret = iwl3945_rate_control_register(); + if (ret) { + IWL_ERROR("Unable to register rate control algorithm: %d\n", ret); + return ret; + } + ret = pci_register_driver(&iwl3945_driver); if (ret) { IWL_ERROR("Unable to initialize PCI module\n"); - return ret; + goto error_register; } #ifdef CONFIG_IWL3945_DEBUG ret = driver_create_file(&iwl3945_driver.driver, &driver_attr_debug_level); if (ret) { IWL_ERROR("Unable to create driver sysfs file\n"); - pci_unregister_driver(&iwl3945_driver); - return ret; + goto error_debug; } #endif return ret; + +#ifdef CONFIG_IWL3945_DEBUG +error_debug: + pci_unregister_driver(&iwl3945_driver); +#endif +error_register: + iwl3945_rate_control_unregister(); + return ret; } static void __exit iwl3945_exit(void) @@ -8846,6 +8361,7 @@ static void __exit iwl3945_exit(void) driver_remove_file(&iwl3945_driver.driver, &driver_attr_debug_level); #endif pci_unregister_driver(&iwl3945_driver); + iwl3945_rate_control_unregister(); } module_param_named(antenna, iwl3945_param_antenna, int, 0444); |