diff --git a/drivers/net/wireless/iwl-3945-hw.h b/drivers/net/wireless/iwl-3945-hw.h index cba2c68..1b5e72f 100644 --- a/drivers/net/wireless/iwl-3945-hw.h +++ b/drivers/net/wireless/iwl-3945-hw.h @@ -75,6 +75,7 @@ #define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE #define IWL_MAX_INST_SIZE ALM_RTC_INST_SIZE #define IWL_MAX_DATA_SIZE ALM_RTC_DATA_SIZE +#define IWL_MAX_NUM_QUEUES 8 static inline int iwl_hw_valid_rtc_data_addr(u32 addr) { diff --git a/drivers/net/wireless/iwl-3945-rs.c b/drivers/net/wireless/iwl-3945-rs.c index 8a98eb8..2eee6c5 100644 --- a/drivers/net/wireless/iwl-3945-rs.c +++ b/drivers/net/wireless/iwl-3945-rs.c @@ -917,8 +917,7 @@ void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) if (!local->rate_ctrl->ops->name || strcmp(local->rate_ctrl->ops->name, RS_NAME)) { - IWL_WARNING("iwl-3945-rs not selected as rate control " - "aglo!\n"); + IWL_WARNING("iwl-3945-rs not selected as rate control algo!\n"); IWL_DEBUG_RATE("leave - mac80211 picked the wrong RC algo.\n"); return; } @@ -972,12 +971,12 @@ void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) iwl_rates[rs_priv->start_rate].plcp); } -void iwl_rate_control_register(void) +void iwl_rate_control_register(struct ieee80211_hw *hw) { ieee80211_rate_control_register(&rs_ops); } -void iwl_rate_control_unregister(void) +void iwl_rate_control_unregister(struct ieee80211_hw *hw) { ieee80211_rate_control_unregister(&rs_ops); } diff --git a/drivers/net/wireless/iwl-3945-rs.h b/drivers/net/wireless/iwl-3945-rs.h index 25bdbcb..70dcec4 100644 --- a/drivers/net/wireless/iwl-3945-rs.h +++ b/drivers/net/wireless/iwl-3945-rs.h @@ -200,7 +200,7 @@ extern void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); * ieee80211_register_hw * */ -extern void iwl_rate_control_register(void); +extern void iwl_rate_control_register(struct ieee80211_hw *hw); /** * iwl_rate_control_unregister - Unregister the rate control callbacks @@ -208,14 +208,14 @@ extern void iwl_rate_control_register(void); * This should be called after calling ieee80211_unregister_hw, but before * the driver is unloaded. */ -extern void iwl_rate_control_unregister(void); +extern void iwl_rate_control_unregister(struct ieee80211_hw *hw); #else static inline int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) { return -ENOTSUPP; } static inline void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) {} -static inline void iwl_rate_control_register(void) {} -static inline void iwl_rate_control_unregister(void) {} +static inline void iwl_rate_control_register(struct ieee80211_hw *hw) {} +static inline void iwl_rate_control_unregister(struct ieee80211_hw *hw) {} #endif /* IWL == 3945 */ #endif diff --git a/drivers/net/wireless/iwl-4965-hw.h b/drivers/net/wireless/iwl-4965-hw.h index 1cf1d4c..858ec55 100644 --- a/drivers/net/wireless/iwl-4965-hw.h +++ b/drivers/net/wireless/iwl-4965-hw.h @@ -98,10 +98,6 @@ enum { CALIB_CH_GROUP_MAX }; -#define POWER_TABLE_NUM_ENTRIES 33 -#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 -#define POWER_TABLE_CCK_ENTRY 32 - /* Temperature calibration offset is 3% 0C in Kelvin */ #define TEMPERATURE_CALIB_KELVIN_OFFSET 8 #define TEMPERATURE_CALIB_A_VAL 259 @@ -208,40 +204,6 @@ union iwl_tx_power_dual_stream { u32 dw; }; -/* in reality this is a complex structure - * so mac it struct to emphasize it*/ -struct tx_power_dual_stream { - __le32 dw; -} __attribute__ ((packed)); - -struct iwl_tx_power_db { - struct tx_power_dual_stream - power_tbl[POWER_TABLE_NUM_ENTRIES]; -} __attribute__ ((packed)); - -struct iwl_tx_power_table_cmd { - u8 band; - u8 channel_normal_width; - __le16 channel; - struct iwl_tx_power_db tx_power; -} __attribute__ ((packed)); - -struct iwl_channel_switch_cmd { - u8 band; - u8 expect_beacon; - __le16 channel; - __le32 rxon_flags; - __le32 rxon_filter_flags; - __le32 switch_time; - struct iwl_tx_power_db tx_power; -} __attribute__ ((packed)); - -struct iwl_channel_switch_notif { - __le16 band; - __le16 channel; - __le32 status; -} __attribute__ ((packed)); - /********************* END TXPOWER *****************************************/ /* HT flags */ @@ -300,43 +262,6 @@ struct iwl_channel_switch_notif { #define is_a_band(tbl) (((tbl) == LQ_A)) #define is_g_and(tbl) (((tbl) == LQ_G)) -/*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */ -#define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1<<0) - -#define LINK_QUAL_AC_NUM AC_NUM -#define LINK_QUAL_MAX_RETRY_NUM 16 - -#define LINK_QUAL_ANT_A_MSK (1<<0) -#define LINK_QUAL_ANT_B_MSK (1<<1) -#define LINK_QUAL_ANT_MSK (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK) - -struct iwl_link_qual_general_params { - u8 flags; - u8 mimo_delimiter; - u8 single_stream_ant_msk; - u8 dual_stream_ant_msk; - u8 start_rate_index[LINK_QUAL_AC_NUM]; -} __attribute__ ((packed)); - -struct iwl_link_qual_agg_params { - __le16 agg_time_limit; - u8 agg_dis_start_th; - u8 agg_frame_cnt_limit; - __le32 reserved; -} __attribute__ ((packed)); - -struct iwl_link_quality_cmd { - u8 sta_id; - u8 reserved1; - __le16 control; - struct iwl_link_qual_general_params general_params; - struct iwl_link_qual_agg_params agg_params; - struct { - __le32 rate_n_flags; - } rs_table[LINK_QUAL_MAX_RETRY_NUM]; - __le32 reserved2; -} __attribute__ ((packed)); - /* Flow Handler Definitions */ /**********************/ @@ -799,50 +724,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u16 flags) { return cpu_to_le32(flags|(u16)rate); } -#if 0 - -union iwl_dram_scratch_union { - struct iwl_dram_scratch s; - __le32 dw; -}; - -struct iwl4965_beacon_notify { - struct iwl_tx_resp beacon_notify_hdr; /*15:4 */ - __le32 low_tsf; /*19:16 */ - __le32 high_tsf; /*23:20 */ - __le32 ibss_mgr_status; /*27:24 */ -} __attribute__ ((packed)); - -struct iwl4965_tx_beacon_cmd { - struct iwl_tx_cmd tx; /*byte 55:4 */ - __le16 tim_idx; /*byte 57:56 */ - u8 tim_size; /*byte 58 */ - u8 reserved1; /*byte 59 */ - struct ieee80211_hdr frame[0]; - /* Beacon Frame */ -} __attribute__ ((packed)); - -struct iwl4965_powertable_cmd { - __le16 flags; - u8 keep_alive_seconds; - u8 debug_flags; - __le32 rx_data_timeout; - __le32 tx_data_timeout; - __le32 sleep_interval[PMC_TCMD_SLEEP_INTRVL_TABLE_SIZE]; - __le32 keep_alive_beacons; -} __attribute__ ((packed)); - -#define IWL_NUM_OF_STATIONS 32 -#define BYTE_CNT_AREA_OFFSET 0 - -enum HT_STATUS { - BA_STATUS_FAILURE = 0, - BA_STATUS_INITIATOR_DELBA, - BA_STATUS_RECIPIENT_DELBA, - BA_STATUS_RENEW_ADDBA_REQUEST, - BA_STATUS_ACTIVE, -}; -#endif #define IWL_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ #define IWL_AGC_DB_POS (7) @@ -898,7 +779,7 @@ struct iwl_tfd_frame { #define IWL4965_MAX_WIN_SIZE 64 #define IWL4965_QUEUE_SIZE 256 #define IWL4965_NUM_FIFOS 7 -#define IWL4965_NUM_QUEUES 16 +#define IWL_MAX_NUM_QUEUES 16 struct iwl4965_queue_byte_cnt_entry { __le16 val; @@ -921,7 +802,7 @@ struct iwl4965_sched_queue_byte_cnt_tbl { * and &iwl_shared.val0 is provided to FH_RSCSR_CHNL0_STTS_WPTR_REG */ struct iwl_shared { struct iwl4965_sched_queue_byte_cnt_tbl - queues_byte_cnt_tbls[IWL4965_NUM_QUEUES]; + queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES]; __le32 val0; /* __le32 rb_closed_stts_rb_num:12; */ diff --git a/drivers/net/wireless/iwl-4965-rs.c b/drivers/net/wireless/iwl-4965-rs.c index 2c354d4..a97914f 100644 --- a/drivers/net/wireless/iwl-4965-rs.c +++ b/drivers/net/wireless/iwl-4965-rs.c @@ -70,14 +70,7 @@ static u8 rs_ht_to_legacy[] = { }; struct iwl_rate { - union { - struct { - u8 rate; - u8 flags; - u16 ext_flags; - } s; - u32 rate_n_flags; - }; + u32 rate_n_flags; } __attribute__ ((packed)); struct iwl_rate_scale_data { @@ -115,7 +108,6 @@ struct iwl_rate_scale_priv { u32 total_success; u8 action_counter; u32 flush_timer; - u8 commit_lq; u8 antenna; u8 valid_antenna; u8 is_green; @@ -187,6 +179,11 @@ static int iwl_lq_sync_callback(struct iwl_priv *priv, return 1; } +static inline u8 iwl_rate_get_rate(u32 rate_n_flags) +{ + return (u8)(rate_n_flags & 0xFF); +} + static int rs_send_lq_cmd(struct iwl_priv *priv, struct iwl_link_quality_cmd *lq, u8 flags) { @@ -216,7 +213,7 @@ static int rs_send_lq_cmd(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) IWL_DEBUG_RATE("lq index %d 0x%X\n", - i, lq->rs_table[i].rate_n_flags); + i, lq->rs_table[i].rate_n_flags); #endif if (flags & CMD_ASYNC) @@ -376,8 +373,7 @@ static int rs_get_tbl_info_from_mcs(const struct iwl_rate *mcs_rate, tbl->lq_type = LQ_NONE; else { - if ((phymode == MODE_ATHEROS_TURBO) || - (phymode == MODE_IEEE80211A)) + if (phymode == MODE_IEEE80211A) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -389,7 +385,8 @@ static int rs_get_tbl_info_from_mcs(const struct iwl_rate *mcs_rate, } *rate_idx = index; - } else if (mcs_rate->s.rate <= IWL_RATE_SISO_60M_PLCP) { + } else if (iwl_rate_get_rate(mcs_rate->rate_n_flags) + <= IWL_RATE_SISO_60M_PLCP) { tbl->lq_type = LQ_SISO; ant_msk = (mcs_rate->rate_n_flags & RATE_MCS_ANT_AB_MSK); @@ -554,8 +551,7 @@ static int rs_get_lower_rate(struct iwl_rate_scale_priv *lq_data, if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) { switch_to_legacy = 1; scale_index = rs_ht_to_legacy[scale_index]; - if ((lq_data->phymode == MODE_IEEE80211A) || - (lq_data->phymode == MODE_ATHEROS_TURBO)) + if (lq_data->phymode == MODE_IEEE80211A) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -572,8 +568,7 @@ static int rs_get_lower_rate(struct iwl_rate_scale_priv *lq_data, /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { - if ((lq_data->phymode == (u8) MODE_IEEE80211A) || - (lq_data->phymode == (u8) MODE_ATHEROS_TURBO)) + if (lq_data->phymode == (u8) MODE_IEEE80211A) rate_mask = (u16)(rate_mask & (sta->supp_rates << IWL_FIRST_OFDM_RATE)); else @@ -866,13 +861,13 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, { struct iwl_scale_tbl_info *active_tbl = &(lq_data->lq_info[lq_data->active_tbl]); - s32 new_rate, high, low; + s32 new_rate, high, low, start_hi; s32 active_sr = active_tbl->win[index].success_ratio; s32 *tpt_tbl = tbl->expected_tpt; s32 active_tpt = active_tbl->expected_tpt[index]; u16 high_low; - new_rate = high = low = IWL_RATE_INVALID; + new_rate = high = low = start_hi = IWL_RATE_INVALID; for (; ;) { high_low = rs_get_adjacent_rate(rate, rate_mask, tbl->lq_type); @@ -886,6 +881,11 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, (tpt_tbl[rate] <= active_tpt))) || ((active_sr >= IWL_RATE_SCALE_SWITCH) && (tpt_tbl[rate] > active_tpt))) { + + if (start_hi != IWL_RATE_INVALID) { + new_rate = start_hi; + break; + } new_rate = rate; if (low != IWL_RATE_INVALID) rate = low; @@ -894,14 +894,15 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, } else { if (new_rate != IWL_RATE_INVALID) break; - else if (high != IWL_RATE_INVALID) + else if (high != IWL_RATE_INVALID) { + start_hi = high; rate = high; - else + } else { + new_rate = rate; break; + } } } - if (new_rate == IWL_RATE_INVALID) - new_rate = rate; return new_rate; } @@ -956,10 +957,7 @@ static int rs_switch_to_mimo(struct iwl_priv *priv, rs_get_expected_tpt_table(lq_data, tbl); - rate = rs_get_best_rate(priv, lq_data, tbl, rate_mask, index, 4); - - if ((rate == IWL_RATE_INVALID) || (rate == 1)) - rate = IWL_RATE_48M_INDEX; + rate = rs_get_best_rate(priv, lq_data, tbl, rate_mask, index, index); IWL_DEBUG_HT("LQ: MIMO best rate %d mask %X\n", rate, rate_mask); if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) @@ -1013,9 +1011,8 @@ static int rs_switch_to_siso(struct iwl_priv *priv, tbl->is_SGI = 0; rs_get_expected_tpt_table(lq_data, tbl); - rate = rs_get_best_rate(priv, lq_data, tbl, rate_mask, index, 4); - if ((rate == IWL_RATE_INVALID) || (rate == 1)) - rate = IWL_RATE_48M_INDEX; + rate = rs_get_best_rate(priv, lq_data, tbl, rate_mask, index, index); + IWL_DEBUG_HT("LQ: get best rate %d mask %X\n", rate, rate_mask); if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { IWL_DEBUG_HT("can not switch with index %d rate mask %x\n", @@ -1043,7 +1040,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; - for (; ; ) { + + for (; ;) { switch (tbl->action) { case IWL_LEGACY_SWITCH_ANTENNA: IWL_DEBUG_HT("LQ Legacy switch Antenna\n"); @@ -1070,8 +1068,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv, search_tbl->lq_type = LQ_SISO; search_tbl->is_SGI = 0; search_tbl->is_fat = 0; - rc = rs_switch_to_siso(priv, lq_data, - search_tbl, index); + rc = rs_switch_to_siso(priv, lq_data, search_tbl, + index); if (!rc) { lq_data->search_better_tbl = 1; lq_data->action_counter = 0; @@ -1087,8 +1085,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv, search_tbl->is_SGI = 0; search_tbl->is_fat = 0; search_tbl->antenna_type = ANT_BOTH; - rc = rs_switch_to_mimo(priv, lq_data, - search_tbl, index); + rc = rs_switch_to_mimo(priv, lq_data, search_tbl, + index); if (!rc) { lq_data->search_better_tbl = 1; lq_data->action_counter = 0; @@ -1161,8 +1159,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, search_tbl->is_SGI = 0; search_tbl->is_fat = 0; search_tbl->antenna_type = ANT_BOTH; - rc = rs_switch_to_mimo(priv, lq_data, - search_tbl, index); + rc = rs_switch_to_mimo(priv, lq_data, search_tbl, + index); if (!rc) lq_data->search_better_tbl = 1; @@ -1243,8 +1241,8 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, else search_tbl->antenna_type = ANT_AUX; - rc = rs_switch_to_siso(priv, lq_data, - search_tbl, index); + rc = rs_switch_to_siso(priv, lq_data, search_tbl, + index); if (!rc) { lq_data->search_better_tbl = 1; goto out; @@ -1411,8 +1409,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { - if ((lq_data->phymode == (u8) MODE_IEEE80211A) || - (lq_data->phymode == (u8) MODE_ATHEROS_TURBO)) + if (lq_data->phymode == (u8) MODE_IEEE80211A) rate_scale_index_msk = (u16) (rate_mask & (sta->supp_rates << IWL_FIRST_OFDM_RATE)); else @@ -1450,18 +1447,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (((fail_count < IWL_RATE_MIN_FAILURE_TH) && (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) || (tbl->expected_tpt == NULL)) { - IWL_DEBUG_RATE("LQ: still below TH succ %d total %d\n", - window->success_counter, window->counter); + IWL_DEBUG_RATE("LQ: still below TH succ %d total %d " + "for index %d\n", + window->success_counter, window->counter, index); window->average_tpt = IWL_INVALID_VALUE; rs_stay_in_table(lq_data); if (update_lq) { rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); - rs_fill_link_cmd(lq_data, &mcs_rate, - &(lq_data->lq), sta); - if (!rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC)) - lq_data->commit_lq = 0; - else - lq_data->commit_lq = 1; + rs_fill_link_cmd(lq_data, &mcs_rate, &lq_data->lq, sta); + rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC); } goto out; @@ -1577,18 +1571,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, break; } - IWL_DEBUG_HT("choose rate scale index %d action %d low %d high %d\n", - index, scale_action, low, high); + IWL_DEBUG_HT("choose rate scale index %d action %d low %d " + "high %d type %d\n", + index, scale_action, low, high, tbl->lq_type); lq_update: if (update_lq) { rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); rs_fill_link_cmd(lq_data, &mcs_rate, &lq_data->lq, sta); - - if (!rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC)) - lq_data->commit_lq = 0; - else - lq_data->commit_lq = 1; + rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC); } rs_stay_in_table(lq_data); @@ -1614,10 +1605,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, tbl->current_rate.rate_n_flags, index); rs_fill_link_cmd(lq_data, &tbl->current_rate, &(lq_data->lq), sta); - if (!rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC)) - lq_data->commit_lq = 0; - else - lq_data->commit_lq = 1; + rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC); } tbl1 = &(lq_data->lq_info[lq_data->active_tbl]); @@ -1657,8 +1645,7 @@ out: /* sta->txrate is an index to A mode rates which start * at IWL_FIRST_OFDM_RATE */ - if ((lq_data->phymode == (u8) MODE_IEEE80211A) || - (lq_data->phymode == (u8) MODE_ATHEROS_TURBO)) + if (lq_data->phymode == (u8) MODE_IEEE80211A) sta->txrate = i - IWL_FIRST_OFDM_RATE; sta->antenna_sel_tx = tbl->lq_type; @@ -1714,7 +1701,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, tbl->current_rate.rate_n_flags = mcs_rate.rate_n_flags; rs_get_expected_tpt_table(lq, tbl); rs_fill_link_cmd(lq, &mcs_rate, &(lq->lq), sta); - lq->commit_lq = 1; + rs_send_lq_cmd(priv, &lq->lq, CMD_ASYNC); out: return; } @@ -1786,20 +1773,12 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate, lq->lq.sta_id = sta_id; lq->lq.rs_table[0].rate_n_flags = 0; lq->ibss_sta_added = 1; - lq->commit_lq = 1; rs_initialize_lq(priv, sta); } if (!lq->ibss_sta_added) goto done; } - - if (lq->commit_lq) { - lq->commit_lq = 0; - if (rs_send_lq_cmd(priv, &lq->lq, CMD_ASYNC)) - lq->commit_lq = 1; - } - done: sta_info_put(sta); if ((i < 0) || (i > IWL_RATE_COUNT)) @@ -1883,8 +1862,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, /* For MODE_IEEE80211A mode cck rate are at end * rate table */ - if ((local->hw.conf.phymode == MODE_IEEE80211A) || - (local->hw.conf.phymode == MODE_ATHEROS_TURBO)) + if (local->hw.conf.phymode == MODE_IEEE80211A) sta->last_txrate += IWL_FIRST_OFDM_RATE; crl->is_dup = priv->is_dup; @@ -1896,15 +1874,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, crl->active_rate_basic = priv->active_rate_basic; crl->phymode = priv->phymode; #ifdef CONFIG_IWLWIFI_HT - crl->active_siso_rate = (priv->active_rate_ht[0] << 1); - crl->active_siso_rate |= (priv->active_rate_ht[0] & 0x1); + crl->active_siso_rate = (priv->current_assoc_ht.supp_rates[0] << 1); + crl->active_siso_rate |= (priv->current_assoc_ht.supp_rates[0] & 0x1); crl->active_siso_rate &= ~((u16)0x2); crl->active_siso_rate = crl->active_siso_rate << IWL_FIRST_OFDM_RATE; - crl->active_mimo_rate = (priv->active_rate_ht[1] << 1); - crl->active_mimo_rate |= (priv->active_rate_ht[1] & 0x1); + crl->active_mimo_rate = (priv->current_assoc_ht.supp_rates[1] << 1); + crl->active_mimo_rate |= (priv->current_assoc_ht.supp_rates[1] & 0x1); crl->active_mimo_rate &= ~((u16)0x2); crl->active_mimo_rate = crl->active_mimo_rate << IWL_FIRST_OFDM_RATE; + IWL_DEBUG_HT("MIMO RATE 0x%X SISO MASK 0x%X\n", crl->active_siso_rate, + crl->active_mimo_rate); #endif /*CONFIG_IWLWIFI_HT*/ if (priv) @@ -1923,7 +1903,6 @@ static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data, u8 use_ht_possible = 1; u8 repeat_cur_rate = 0; struct iwl_rate new_rate; - struct iwl_rate tbl_rate; struct iwl_scale_tbl_info tbl_type = { 0 }; rs_get_tbl_info_from_mcs(tx_mcs, lq_data->phymode, @@ -1935,10 +1914,10 @@ static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data, } else repeat_cur_rate = IWL_HT_NUMBER_TRY; - lq_cmd->rs_table[index].rate_n_flags = - cpu_to_le32(tx_mcs->rate_n_flags); lq_cmd->general_params.mimo_delimiter = is_mimo(tbl_type.lq_type) ? 1 : 0; + lq_cmd->rs_table[index].rate_n_flags = + cpu_to_le32(tx_mcs->rate_n_flags); new_rate.rate_n_flags = tx_mcs->rate_n_flags; if (is_mimo(tbl_type.lq_type) || (tbl_type.antenna_type == ANT_MAIN)) @@ -1965,10 +1944,10 @@ static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data, repeat_cur_rate--; index++; } - tbl_rate.rate_n_flags = - le32_to_cpu(lq_cmd->rs_table[index - 1].rate_n_flags); - rs_get_tbl_info_from_mcs(&tbl_rate, lq_data->phymode, &tbl_type, - &rate_idx); + + rs_get_tbl_info_from_mcs(&new_rate, lq_data->phymode, &tbl_type, + &rate_idx); + if (is_mimo(tbl_type.lq_type)) lq_cmd->general_params.mimo_delimiter = index; @@ -2150,12 +2129,12 @@ void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) priv->lq_mngr.lq_ready = 1; } -void iwl_rate_control_register(void) +void iwl_rate_control_register(struct ieee80211_hw *hw) { ieee80211_rate_control_register(&rs_ops); } -void iwl_rate_control_unregister(void) +void iwl_rate_control_unregister(struct ieee80211_hw *hw) { ieee80211_rate_control_unregister(&rs_ops); } diff --git a/drivers/net/wireless/iwl-4965-rs.h b/drivers/net/wireless/iwl-4965-rs.h index b1fb0f0..aa9aae5 100644 --- a/drivers/net/wireless/iwl-4965-rs.h +++ b/drivers/net/wireless/iwl-4965-rs.h @@ -265,7 +265,7 @@ extern void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); * ieee80211_register_hw * */ -extern void iwl_rate_control_register(void); +extern void iwl_rate_control_register(struct ieee80211_hw *hw); /** * iwl_rate_control_unregister - Unregister the rate control callbacks @@ -273,14 +273,14 @@ extern void iwl_rate_control_register(void); * This should be called after calling ieee80211_unregister_hw, but before * the driver is unloaded. */ -extern void iwl_rate_control_unregister(void); +extern void iwl_rate_control_unregister(struct ieee80211_hw *hw); #else static inline int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) { return -ENOTSUPP; } static inline void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) {} -static inline void iwl_rate_control_register(void) {} -static inline void iwl_rate_control_unregister(void) {} +static inline void iwl_rate_control_register(struct ieee80211_hw *hw) {} +static inline void iwl_rate_control_unregister(struct ieee80211_hw *hw) {} #endif /* IWL == 4965 */ #endif diff --git a/drivers/net/wireless/iwl-4965.c b/drivers/net/wireless/iwl-4965.c index 5f9b699..a78cc8c 100644 --- a/drivers/net/wireless/iwl-4965.c +++ b/drivers/net/wireless/iwl-4965.c @@ -203,6 +203,7 @@ static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) if (!pwr_max) { u32 val; + rc = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE, &val); @@ -393,7 +394,7 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) } /* Tx queue(s) */ - for (txq_id = 0; txq_id < priv->hw_setting.max_queue_number; txq_id++) { + for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, @@ -601,7 +602,7 @@ void iwl_hw_txq_ctx_stop(struct iwl_priv *priv) unsigned long flags; /* reset TFD queues */ - for (txq_id = 0; txq_id < IWL4965_NUM_QUEUES; txq_id++) { + for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { spin_lock_irqsave(&priv->lock, flags); if (iwl_grab_restricted_access(priv)) { spin_unlock_irqrestore(&priv->lock, flags); @@ -1657,7 +1658,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl_write_restricted_mem(priv, a, 0); for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4) iwl_write_restricted_mem(priv, a, 0); - for (; a < sizeof(u16) * IWL4965_NUM_QUEUES; a += 4) + for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4) iwl_write_restricted_mem(priv, a, 0); iwl_write_restricted_reg(priv, SCD_DRAM_BASE_ADDR, @@ -1666,7 +1667,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl_write_restricted_reg(priv, SCD_QUEUECHAIN_SEL, 0); /* initiate the queues */ - for (i = 0; i < IWL4965_NUM_QUEUES; i++) { + for (i = 0; i < priv->hw_setting.max_txq_num; i++) { iwl_write_restricted_reg(priv, SCD_QUEUE_RDPTR(i), 0); iwl_write_restricted(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); iwl_write_restricted_mem(priv, priv->scd_base_addr + @@ -1683,7 +1684,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) } iwl_write_restricted_reg(priv, SCD_INTERRUPT_MASK, - (1 << IWL4965_NUM_QUEUES) - 1); + (1 << priv->hw_setting.max_txq_num) - 1); iwl_write_restricted_reg(priv, SCD_TXFACT, SCD_TXFACT_REG_TXFIFO_MASK(0, 7)); @@ -1717,7 +1718,7 @@ int iwl_hw_set_hw_setting(struct iwl_priv *priv) memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl_shared)); - priv->hw_setting.max_queue_number = IWL4965_NUM_QUEUES; + priv->hw_setting.max_txq_num = iwl_param_queues_num; priv->hw_setting.ac_queue_count = AC_NUM; priv->hw_setting.cck_flag = RATE_MCS_CCK_MSK; @@ -1738,7 +1739,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) int txq_id; /* Tx queues */ - for (txq_id = 0; txq_id < priv->hw_setting.max_queue_number; txq_id++) + for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) iwl_tx_queue_free(priv, &priv->txq[txq_id]); iwl4965_kw_free(priv); @@ -2534,8 +2535,7 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv) } band = ((priv->phymode == MODE_IEEE80211B) || - (priv->phymode == MODE_IEEE80211G) || - (priv->phymode == MODE_ATHEROS_TURBOG)) ? 1 : 0; + (priv->phymode == MODE_IEEE80211G)); is_fat = is_fat_channel(priv->active_rxon.flags); @@ -2567,8 +2567,7 @@ int iwl_hw_channel_switch(struct iwl_priv *priv, u16 channel) const struct iwl_channel_info *ch_info; band = ((priv->phymode == MODE_IEEE80211B) || - (priv->phymode == MODE_IEEE80211G) || - (priv->phymode == MODE_ATHEROS_TURBOG)) ? 1 : 0; + (priv->phymode == MODE_IEEE80211G)); ch_info = iwl_get_channel_info(priv, priv->phymode, channel); @@ -2989,12 +2988,11 @@ static u8 iwl4964_tl_ba_avail(struct iwl_priv *priv) static void iwl4965_ba_status(struct iwl_priv *priv, u8 tid, enum HT_STATUS status); -static int iwl4965_perform_addba(struct iwl_priv *priv, u8 tid, - u32 length, u32 ba_timeout) +static int iwl4965_perform_addba(struct iwl_priv *priv, u8 tid, u32 length, + u32 ba_timeout) { - int rc = 0; + int rc; - IWL_WARNING("ZZZY we are staring Tx agg\n"); rc = ieee80211_start_BA_session(priv->hw, priv->bssid, tid); if (rc) iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE); @@ -3004,18 +3002,18 @@ static int iwl4965_perform_addba(struct iwl_priv *priv, u8 tid, static int iwl4965_perform_delba(struct iwl_priv *priv, u8 tid) { - int rc = 0; + int rc; rc = ieee80211_stop_BA_session(priv->hw, priv->bssid, tid); - if (rc) iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE); + return rc; } static void iwl4965_turn_on_agg_for_tid(struct iwl_priv *priv, - struct iwl_lq_mngr *lq, - u8 auto_agg, u8 tid) + struct iwl_lq_mngr *lq, + u8 auto_agg, u8 tid) { u32 tid_msk = (1 << tid); unsigned long flags; @@ -3724,14 +3722,15 @@ static int parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems) static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { - unsigned long lock_flags; - spin_lock_irqsave(&priv->sta_lock, lock_flags); + unsigned long flags; + + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.sta.modify_mask = 0; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, lock_flags); - /* assuming we are in rx flow and the lock is already locked */ + spin_unlock_irqrestore(&priv->sta_lock, flags); + iwl_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } @@ -3739,9 +3738,11 @@ static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) { /* FIXME: need locking over ps_status ??? */ u8 sta_id = iwl_hw_find_station(priv, addr); + if (sta_id != IWL_INVALID_STATION) { u8 sta_awake = priv->stations[sta_id]. ps_status == STA_PS_STATUS_WAKE; + if (sta_awake && ps_bit) priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; else if (!sta_awake && !ps_bit) { @@ -3749,7 +3750,6 @@ static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; } } - } /* Called for REPLY_4965_RX (legacy ABG frames), or @@ -4059,13 +4059,13 @@ static void iwl4965_set_tx_status(struct iwl_priv *priv, int txq_id, int idx, static void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid) { - unsigned long lock_flags; + unsigned long flags; - spin_lock_irqsave(&priv->sta_lock, lock_flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, lock_flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); iwl_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } @@ -4113,7 +4113,7 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv, ack = bitmap0 & (1 << i); IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", ack? "ACK":"NACK", i, idx, agg->start_idx + i); - iwl4965_set_tx_status(priv, ba_resp->tid, idx, ack, 1, + iwl4965_set_tx_status(priv, agg->txq_id, idx, ack, 1, agg->rate_n_flags); } @@ -4343,8 +4343,7 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) * all the way to 1M in IEEE order and then spin on IEEE */ if (is_ap) r = IWL_RATE_54M_INDEX; - else if ((priv->phymode == MODE_IEEE80211A) || - (priv->phymode == MODE_ATHEROS_TURBO)) + else if (priv->phymode == MODE_IEEE80211A) r = IWL_RATE_6M_INDEX; else r = IWL_RATE_1M_INDEX; @@ -4408,16 +4407,14 @@ static u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, return 0; /* no fat tx allowed on 2.4GHZ */ - if ((priv->phymode != MODE_IEEE80211A) && - (priv->phymode != MODE_ATHEROS_TURBO)) + if (priv->phymode != MODE_IEEE80211A) return 0; return (iwl_is_channel_extension(priv, priv->phymode, ht_info->control_channel, ht_info->extension_chan_offset)); } -void iwl4965_set_rxon_ht(struct iwl_priv *priv, - struct sta_ht_info *ht_info) +void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct sta_ht_info *ht_info) { struct iwl_rxon_cmd *rxon = &priv->staging_rxon; u32 val; @@ -4517,29 +4514,31 @@ void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index) static void iwl4965_sta_modify_add_ba_tid(struct iwl_priv *priv, int sta_id, int tid, u16 ssn) { - unsigned long lock_flags; + unsigned long flags; - spin_lock_irqsave(&priv->sta_lock, lock_flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, lock_flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); + iwl_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } static void iwl4965_sta_modify_del_ba_tid(struct iwl_priv *priv, int sta_id, int tid) { - unsigned long lock_flags; + unsigned long flags; - spin_lock_irqsave(&priv->sta_lock, lock_flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, lock_flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); + iwl_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } @@ -4567,7 +4566,7 @@ static int iwl_txq_ctx_activate_free(struct iwl_priv *priv) { int txq_id; - for (txq_id = 0; txq_id < IWL4965_NUM_QUEUES; txq_id++) + for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) return txq_id; return -1; diff --git a/drivers/net/wireless/iwl-4965.h b/drivers/net/wireless/iwl-4965.h index d679281..af5215f 100644 --- a/drivers/net/wireless/iwl-4965.h +++ b/drivers/net/wireless/iwl-4965.h @@ -187,7 +187,6 @@ struct iwl_lq_mngr { #endif spinlock_t lock; s32 max_window_size; - struct iwl_rate_scaling_cmd scale_rate_cmd; s32 *expected_tpt; u8 *next_higher_rate; u8 *next_lower_rate; diff --git a/drivers/net/wireless/iwl-base.c b/drivers/net/wireless/iwl-base.c index 02ae2f0..4b80728 100644 --- a/drivers/net/wireless/iwl-base.c +++ b/drivers/net/wireless/iwl-base.c @@ -78,6 +78,7 @@ int iwl_param_disable; /* def: enable radio */ int iwl_param_antenna; /* def: 0 = both antennas (use diversity) */ int iwl_param_hwcrypto; /* def: using software encryption */ int iwl_param_qos_enable = 1; +int iwl_param_queues_num = IWL_MAX_NUM_QUEUES; /* * module name, copyright, version, etc. @@ -100,13 +101,13 @@ BUILD_BUG() #define VD #endif -#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENY +#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT #define VS "s" #else #define VS #endif -#define IWLWIFI_VERSION "0.1.8k" VD VS +#define IWLWIFI_VERSION "0.1.11k" VD VS #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" #define DRV_VERSION IWLWIFI_VERSION @@ -187,17 +188,11 @@ static const char *iwl_escape_essid(const char *essid, u8 essid_len) static void iwl_print_hex_dump(int level, void *p, u32 len) { #ifdef CONFIG_IWLWIFI_DEBUG - u32 ofs = 0; - if (!(iwl_debug_level & level)) return; - while (len) { - print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, - 16, 1, p + ofs, len, 1); - ofs += 16; - len -= min(len, 16U); - } + print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, + p, len, 1); #endif } @@ -579,7 +574,7 @@ static inline int iwl_is_init(struct iwl_priv *priv) static inline int iwl_is_rfkill(struct iwl_priv *priv) { - return test_bit(STATUS_RF_KILL_HW, &priv->status) | + return test_bit(STATUS_RF_KILL_HW, &priv->status) || test_bit(STATUS_RF_KILL_SW, &priv->status); } @@ -695,7 +690,7 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -ENOSPC; } - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->hcmd_lock, flags); tfd = &txq->bd[q->first_empty]; memset(tfd, 0, sizeof(*tfd)); @@ -744,7 +739,7 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) rc = iwl_tx_queue_update_write_ptr(priv, txq); #endif - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->hcmd_lock, flags); return rc ? rc : idx; } @@ -765,6 +760,8 @@ static int __iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { + int ret; + BUG_ON(!(cmd->meta.flags & CMD_ASYNC)); /* An asynchronous command can not expect an SKB to be set. */ @@ -776,7 +773,11 @@ int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EBUSY; - return __iwl_send_cmd(priv, cmd); + ret = __iwl_send_cmd(priv, cmd); + if (ret < 0) + return ret; + + return 0; } int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) @@ -948,8 +949,7 @@ static int iwl_set_rxon_channel(struct iwl_priv *priv, u8 phymode, u16 channel) return 0; priv->staging_rxon.channel = cpu_to_le16(channel); - if ((phymode == MODE_IEEE80211A) || - (phymode == MODE_ATHEROS_TURBO)) + if (phymode == MODE_IEEE80211A) priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; else priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; @@ -2543,8 +2543,7 @@ static int iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode) { - if ((phymode == MODE_IEEE80211A) || - (phymode == MODE_ATHEROS_TURBO)) { + if (phymode == MODE_IEEE80211A) { priv->staging_rxon.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); @@ -2827,14 +2826,23 @@ static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) is_multicast_ether_addr(hdr->addr1)) return IWL_BROADCAST_ID; + switch (priv->iw_mode) { + /* If this frame is part of a BSS network (we're a station), then * we use the AP's station id */ - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) + case IEEE80211_IF_TYPE_STA: return IWL_AP_ID; + /* If we are an AP, then find the station, or use BCAST */ + case IEEE80211_IF_TYPE_AP: + sta_id = iwl_hw_find_station(priv, hdr->addr1); + if (sta_id != IWL_INVALID_STATION) + return sta_id; + return IWL_BROADCAST_ID; + /* If this frame is part of a IBSS network, then we use the * target specific station id */ - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) { + case IEEE80211_IF_TYPE_IBSS: sta_id = iwl_hw_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -2849,10 +2857,11 @@ static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) MAC_ARG(hdr->addr1)); iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); return IWL_BROADCAST_ID; - } - /* Otherwise we default to the broadcast station id */ - return IWL_BROADCAST_ID; + default: + IWL_WARNING("Unkown mode of operation: %d", priv->iw_mode); + return IWL_BROADCAST_ID; + } } /* @@ -3084,8 +3093,7 @@ static void iwl_set_rate(struct iwl_priv *priv) priv->active_rate_basic = 0; IWL_DEBUG_RATE("Setting rates for 802.11%c\n", - ((hw->mode == MODE_IEEE80211A) || - (hw->mode == MODE_ATHEROS_TURBO)) ? + hw->mode == MODE_IEEE80211A ? 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g')); for (i = 0; i < hw->num_rates; i++) { @@ -3532,8 +3540,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; - u8 hcmd_num = 0; - int used; + 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, " @@ -3541,16 +3548,20 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) index, q->n_bd, q->first_empty, q->last_used); return 0; } - index = iwl_queue_inc_wrap(index, q->n_bd); - for (; q->last_used != index; - q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd)) { + for (index = iwl_queue_inc_wrap(index, q->n_bd); + q->last_used != index; + q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd)) { if (txq_id != IWL_CMD_QUEUE_NUM) { iwl_txstatus_to_ieee(priv, &(txq->txb[txq->q.last_used])); iwl_hw_txq_free_tfd(priv, txq); - } else - hcmd_num++; + } else if (nfreed > 1) { + IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, + q->first_empty, q->last_used); + queue_work(priv->workqueue, &priv->restart); + } + nfreed++; } if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && @@ -3558,17 +3569,8 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) priv->mac80211_registered) ieee80211_wake_queue(priv->hw, txq_id); - used = q->first_empty - q->last_used; - if (used < 0) - used += q->n_bd; - if (hcmd_num > 1) { - IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, - q->first_empty, q->last_used); - queue_work(priv->workqueue, &priv->restart); - } - - return used; + return nfreed; } static int iwl_is_tx_success(u32 status) @@ -3640,16 +3642,16 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, agg->bitmap0 = agg->bitmap1 = 0; if (agg->frame_count == 1) { + struct iwl_tx_queue *txq ; status = le32_to_cpu(frame_status[0]); - seq = status >> 16; - idx = SEQ_TO_INDEX(seq); - txq_id = SEQ_TO_QUEUE(seq); + txq_id = agg->txq_id; + txq = &priv->txq[txq_id]; /* FIXME: code repetition */ - IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", - agg->frame_count, agg->start_idx, idx); + IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d \n", + agg->frame_count, agg->start_idx); - tx_status = &(priv->txq[txq_id].txb[idx].status); + tx_status = &(priv->txq[txq_id].txb[txq->q.last_used].status); tx_status->retry_count = tx_resp->failure_frame; tx_status->queue_number = status & 0xff; tx_status->queue_length = tx_resp->bt_kill_count; @@ -3661,8 +3663,8 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags); /* FIXME: code repetition end */ - IWL_DEBUG_TX_REPLY("1 Frame 0x%x idx %d failure :%d\n", - status & 0xff, idx, tx_resp->failure_frame); + IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", + status & 0xff, tx_resp->failure_frame); IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n", iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags)); @@ -3794,7 +3796,7 @@ static void iwl_rx_reply_tx(struct iwl_priv *priv, /* TODO: send BAR */ } - if (txq->q.last_used != (scd_ssn & 0xff)) { + if ((txq->q.last_used != (scd_ssn & 0xff))) { index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " "%d index %d\n", scd_ssn , index); @@ -3960,6 +3962,31 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); } +static void iwl_bg_beacon_update(struct work_struct *work) +{ + struct iwl_priv *priv = + container_of(work, struct iwl_priv, beacon_update); + struct sk_buff *beacon; + + /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ + beacon = ieee80211_beacon_get(priv->hw, priv->interface_id, NULL); + + if (!beacon) { + IWL_ERROR("update beacon failed\n"); + return; + } + + mutex_lock(&priv->mutex); + /* new beacon skb is allocated every time; dispose previous.*/ + if (priv->ibss_beacon) + dev_kfree_skb(priv->ibss_beacon); + + priv->ibss_beacon = beacon; + mutex_unlock(&priv->mutex); + + iwl_send_beacon_cmd(priv); +} + static void iwl_rx_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -3979,20 +4006,26 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, le32_to_cpu(beacon->high_tsf), le32_to_cpu(beacon->low_tsf), rate); #endif + + if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + (!test_bit(STATUS_EXIT_PENDING, &priv->status))) + queue_work(priv->workqueue, &priv->beacon_update); } +/* Service response to REPLY_SCAN_CMD (0x80) */ static void iwl_rx_reply_scan(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl_scanstart_notification *notif = - (struct iwl_scanstart_notification *)pkt->u.raw; + struct iwl_scanreq_notification *notif = + (struct iwl_scanreq_notification *)pkt->u.raw; IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status); #endif } +/* Service SCAN_START_NOTIFICATION (0x82) */ static void iwl_rx_scan_start_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -4009,6 +4042,7 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv, notif->tsf_low, notif->status, notif->beacon_timer); } +/* Service SCAN_RESULTS_NOTIFICATION (0x83) */ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -4032,6 +4066,7 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, priv->last_scan_jiffies = jiffies; } +/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -5409,7 +5444,6 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv, int i; switch (phymode) { - case MODE_ATHEROS_TURBO: case MODE_IEEE80211A: for (i = 14; i < priv->channel_count; i++) { if (priv->channel_info[i].channel == channel) @@ -5419,7 +5453,6 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv, case MODE_IEEE80211B: case MODE_IEEE80211G: - case MODE_ATHEROS_TURBOG: if (channel >= 1 && channel <= 14) return &priv->channel_info[channel - 1]; break; @@ -5604,8 +5637,7 @@ static int iwl_init_channel_map(struct iwl_priv *priv) static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, int phymode) { - if ((phymode == MODE_IEEE80211A) || - (phymode == MODE_ATHEROS_TURBO)) + if (phymode == MODE_IEEE80211A) return IWL_ACTIVE_DWELL_TIME_52; else return IWL_ACTIVE_DWELL_TIME_24; @@ -5614,8 +5646,7 @@ static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, int phymode) static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, int phymode) { u16 active = iwl_get_active_dwell_time(priv, phymode); - u16 passive = ((phymode != MODE_IEEE80211A) && - (phymode != MODE_ATHEROS_TURBO)) ? + u16 passive = (phymode != MODE_IEEE80211A) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -5696,8 +5727,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode, /* scan_pwr_info->tpc.dsp_atten; */ /*scan_pwr_info->tpc.tx_gain; */ - if ((phymode == MODE_IEEE80211A) || - (phymode == MODE_ATHEROS_TURBO)) + if (phymode == MODE_IEEE80211A) scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; else { scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); @@ -5850,13 +5880,13 @@ static int iwl_init_geos(struct iwl_priv *priv) modes[G].num_channels = 0; #if IWL == 4965 - modes[G_11N].mode = MODE_ATHEROS_TURBOG; + modes[G_11N].mode = MODE_IEEE80211G; modes[G_11N].channels = channels; modes[G_11N].num_rates = 13; /* OFDM & CCK */ modes[G_11N].rates = rates; modes[G_11N].num_channels = 0; - modes[A_11N].mode = MODE_ATHEROS_TURBO; + modes[A_11N].mode = MODE_IEEE80211A; modes[A_11N].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; modes[A_11N].rates = &rates[4]; modes[A_11N].num_rates = 9; /* just OFDM */ @@ -6559,7 +6589,7 @@ static int iwl_set_ucode_ptrs(struct iwl_priv *priv) /* Inst bytecount must be last to set up, bit 31 signals uCode * that all new ptr/size info is in place */ iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG, - priv->ucode_code.len | 0x80000000); + priv->ucode_code.len | BSM_DRAM_INST_LOAD); iwl_release_restricted_access(priv); @@ -6712,7 +6742,7 @@ static void iwl_alive_start(struct iwl_priv *priv) /* Unlock so any user space entry points can call back into * the driver without a deadlock... */ mutex_unlock(&priv->mutex); - iwl_rate_control_register(); + iwl_rate_control_register(priv->hw); rc = ieee80211_register_hw(priv->hw); priv->hw->conf.beacon_int = 100; mutex_lock(&priv->mutex); @@ -7796,9 +7826,9 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id, * to verify) - jpk */ memcpy(priv->bssid, conf->bssid, ETH_ALEN); - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == IEEE80211_IF_TYPE_AP) iwl_config_ap(priv); - } else { + else { priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; rc = iwl_commit_rxon(priv); @@ -7914,8 +7944,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, set_key_cmd cmd, u8 *addr, sta_id = iwl_hw_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211("leave - " MAC_FMT - " not in station map.\n", MAC_ARG(addr)); + IWL_DEBUG_MAC80211("leave - " MAC_FMT " not in station map.\n", + MAC_ARG(addr)); return -EINVAL; } @@ -7929,14 +7959,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, set_key_cmd cmd, u8 *addr, if (!rc) { iwl_set_rxon_hwcrypto(priv, 1); iwl_commit_rxon(priv); - key->flags &= (u32) - (~IEEE80211_KEY_FORCE_SW_ENCRYPT); + key->flags &= ~IEEE80211_KEY_FORCE_SW_ENCRYPT; key->hw_key_idx = sta_id; - /* TODO do we need below */ - /* - * conf->sw_encrypt = 0; - * conf->sw_decrypt = 0; - */ IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n"); } @@ -8265,6 +8289,10 @@ static int sta_ht_info_init(struct ieee80211_ht_capability *ht_cap, ht_info->ampdu_factor = param_info.max_rx_ampdu_factor; ht_info->mpdu_density = param_info.mpdu_density; + IWL_DEBUG_MAC80211("SISO mask 0x%X MIMO mask 0x%X \n", + ht_cap->supported_mcs_set[0], + ht_cap->supported_mcs_set[1]); + if (ht_info_ap) { ht_info->control_channel = ht_info_ap->control_channel; ht_info->extension_chan_offset = @@ -8361,8 +8389,7 @@ static void iwl_mac_get_ht_capab(struct ieee80211_hw *hw, use_wide_channel = 0; /* no fat tx allowed on 2.4GHZ */ - if ((priv->phymode != MODE_IEEE80211A) && - (priv->phymode != MODE_ATHEROS_TURBO)) + if (priv->phymode != MODE_IEEE80211A) use_wide_channel = 0; iwl_set_ht_capab(hw, ht_cap, use_wide_channel); @@ -9041,6 +9068,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->request_scan, iwl_bg_request_scan); INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill); + INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); INIT_DELAYED_WORK(&priv->post_associate, iwl_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); @@ -9059,6 +9087,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); cancel_delayed_work(&priv->post_associate); + cancel_work_sync(&priv->beacon_update); } static struct attribute *iwl_sysfs_entries[] = { @@ -9120,7 +9149,6 @@ static struct ieee80211_ops iwl_hw_ops = { #endif /* CONFIG_IWLWIFI_HT */ #endif .hw_scan = iwl_mac_hw_scan - }; static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -9136,6 +9164,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_hw_ops.hw_scan = NULL; } + if ((iwl_param_queues_num > IWL_MAX_NUM_QUEUES) || + (iwl_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); + err = -EINVAL; + goto out; + } + /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl_hw_ops); @@ -9185,6 +9221,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) spin_lock_init(&priv->lock); spin_lock_init(&priv->power_data.lock); spin_lock_init(&priv->sta_lock); + spin_lock_init(&priv->hcmd_lock); #if IWL == 4965 spin_lock_init(&priv->lq_mngr.lock); #endif @@ -9407,7 +9444,7 @@ static void iwl_pci_remove(struct pci_dev *pdev) if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); - iwl_rate_control_unregister(); + iwl_rate_control_unregister(priv->hw); } /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes @@ -9595,6 +9632,9 @@ MODULE_PARM_DESC(debug, "debug output mask"); module_param_named(disable_hw_scan, iwl_param_disable_hw_scan, int, 0444); MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); +module_param_named(queues_num, iwl_param_queues_num, int, 0444); +MODULE_PARM_DESC(queues_num, "number of hw queues."); + /* QoS */ module_param_named(qos_enable, iwl_param_qos_enable, int, 0444); MODULE_PARM_DESC(qos_enable, "enable all QoS functionality"); diff --git a/drivers/net/wireless/iwl-channel.h b/drivers/net/wireless/iwl-channel.h index 97da370..023c3f2 100644 --- a/drivers/net/wireless/iwl-channel.h +++ b/drivers/net/wireless/iwl-channel.h @@ -136,15 +136,13 @@ static inline int is_channel_radar(const struct iwl_channel_info *ch_info) static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info) { - return ((ch_info->phymode == MODE_IEEE80211A) || - (ch_info->phymode == MODE_ATHEROS_TURBO)) ? 1 : 0; + return ch_info->phymode == MODE_IEEE80211A; } static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info) { return ((ch_info->phymode == MODE_IEEE80211B) || - (ch_info->phymode == MODE_IEEE80211G) || - (ch_info->phymode == MODE_ATHEROS_TURBOG)) ? 1 : 0; + (ch_info->phymode == MODE_IEEE80211G)); } static inline int is_channel_passive(const struct iwl_channel_info *ch) diff --git a/drivers/net/wireless/iwl-commands.h b/drivers/net/wireless/iwl-commands.h index 5ce9847..7f39b03 100644 --- a/drivers/net/wireless/iwl-commands.h +++ b/drivers/net/wireless/iwl-commands.h @@ -68,7 +68,7 @@ enum { REPLY_ALIVE = 0x1, REPLY_ERROR = 0x2, - /* RXON state commands */ + /* RXON and QOS commands */ REPLY_RXON = 0x10, REPLY_RXON_ASSOC = 0x11, REPLY_QOS_PARAM = 0x13, @@ -76,29 +76,27 @@ enum { /* Multi-Station support */ REPLY_ADD_STA = 0x18, - REPLY_REMOVE_STA = 0x19, - REPLY_REMOVE_ALL_STA = 0x1a, + REPLY_REMOVE_STA = 0x19, /* not used */ + REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ - /* RX, TX */ + /* RX, TX, LEDs */ #if IWL == 3945 - REPLY_3945_RX = 0x1b, + REPLY_3945_RX = 0x1b, /* 3945 only */ #endif REPLY_TX = 0x1c, - - /* MISC commands */ - REPLY_RATE_SCALE = 0x47, + REPLY_RATE_SCALE = 0x47, /* 3945 only */ REPLY_LEDS_CMD = 0x48, - REPLY_TX_LINK_QUALITY_CMD = 0x4e, + REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ /* 802.11h related */ - RADAR_NOTIFICATION = 0x70, - REPLY_QUIET_CMD = 0x71, + RADAR_NOTIFICATION = 0x70, /* not used */ + REPLY_QUIET_CMD = 0x71, /* not used */ REPLY_CHANNEL_SWITCH = 0x72, CHANNEL_SWITCH_NOTIFICATION = 0x73, REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74, SPECTRUM_MEASURE_NOTIFICATION = 0x75, - /* Power Management *** */ + /* Power Management */ POWER_TABLE_CMD = 0x77, PM_SLEEP_NOTIFICATION = 0x7A, PM_DEBUG_STATISTIC_NOTIFIC = 0x7B, @@ -106,7 +104,6 @@ enum { /* Scan commands and notifications */ REPLY_SCAN_CMD = 0x80, REPLY_SCAN_ABORT_CMD = 0x81, - SCAN_START_NOTIFICATION = 0x82, SCAN_RESULTS_NOTIFICATION = 0x83, SCAN_COMPLETE_NOTIFICATION = 0x84, @@ -114,18 +111,21 @@ enum { /* IBSS/AP commands */ BEACON_NOTIFICATION = 0x90, REPLY_TX_BEACON = 0x91, - WHO_IS_AWAKE_NOTIFICATION = 0x94, + WHO_IS_AWAKE_NOTIFICATION = 0x94, /* not used */ - QUIET_NOTIFICATION = 0x96, + /* Miscellaneous commands */ + QUIET_NOTIFICATION = 0x96, /* not used */ REPLY_TX_PWR_TABLE_CMD = 0x97, - MEASURE_ABORT_NOTIFICATION = 0x99, + MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ /* BT config command */ REPLY_BT_CONFIG = 0x9b, + + /* 4965 Statistics */ REPLY_STATISTICS_CMD = 0x9c, STATISTICS_NOTIFICATION = 0x9d, - /* RF-KILL commands and notifications *** */ + /* RF-KILL commands and notifications */ REPLY_CARD_STATE_CMD = 0xa0, CARD_STATE_NOTIFICATION = 0xa1, @@ -178,13 +178,12 @@ struct iwl_cmd_header { * *****************************************************************************/ -/* - * Alive Command & Response - */ - #define UCODE_VALID_OK __constant_cpu_to_le32(0x1) #define INITIALIZE_SUBTYPE (9) +/* + * REPLY_ALIVE = 0x1 (response only, not a command) + */ struct iwl_alive_resp { u8 ucode_minor; u8 ucode_major; @@ -224,16 +223,15 @@ struct iwl_init_alive_resp { #endif } __attribute__ ((packed)); -/* - * Error Command & Response - */ - union tsf { u8 byte[8]; __le16 word[4]; __le32 dw[2]; }; +/* + * REPLY_ERROR = 0x2 (response only, not a command) + */ struct iwl_error_resp { __le32 error_type; u8 cmd_id; @@ -303,7 +301,7 @@ enum { #define RXON_FILTER_BCON_AWARE_MSK __constant_cpu_to_le32(1 << 6) /* - * RXON Command + * REPLY_RXON = 0x10 (command, has simple generic response) */ struct iwl_rxon_cmd { u8 node_addr[6]; @@ -334,7 +332,7 @@ struct iwl_rxon_cmd { } __attribute__ ((packed)); /* - * RXON-ASSOCIATED Command + * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) */ struct iwl_rxon_assoc_cmd { __le32 flags; @@ -350,7 +348,7 @@ struct iwl_rxon_assoc_cmd { } __attribute__ ((packed)); /* - * RXON-Timings Command & Response + * REPLY_RXON_TIMING = 0x14 (command, has simple generic response) */ struct iwl_rxon_time_cmd { union tsf timestamp; @@ -361,14 +359,62 @@ struct iwl_rxon_time_cmd { __le16 reserved; } __attribute__ ((packed)); +struct iwl_tx_power { + u8 tx_gain; /* gain for analog radio */ + u8 dsp_atten; /* gain for DSP */ +} __attribute__ ((packed)); + +#if IWL == 3945 +struct iwl_power_per_rate { + u8 rate; /* plcp */ + struct iwl_tx_power tpc; + u8 reserved; +} __attribute__ ((packed)); + +#elif IWL == 4965 +#define POWER_TABLE_NUM_ENTRIES 33 +#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 +#define POWER_TABLE_CCK_ENTRY 32 +struct tx_power_dual_stream { + __le32 dw; +} __attribute__ ((packed)); + +struct iwl_tx_power_db { + struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES]; +} __attribute__ ((packed)); +#endif + +/* + * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) + */ +struct iwl_channel_switch_cmd { + u8 band; + u8 expect_beacon; + __le16 channel; + __le32 rxon_flags; + __le32 rxon_filter_flags; + __le32 switch_time; +#if IWL == 3945 + struct iwl_power_per_rate power[IWL_MAX_RATES]; +#elif IWL == 4965 + struct iwl_tx_power_db tx_power; +#endif +} __attribute__ ((packed)); + +/* + * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command) + */ +struct iwl_csa_notification { + __le16 band; + __le16 channel; + __le32 status; /* 0 - OK, 1 - fail */ +} __attribute__ ((packed)); + /****************************************************************************** * (2) * Quality-of-Service (QOS) Commands & Responses: * *****************************************************************************/ -/* - * beacon QOS parameters Command & Response - */ struct iwl_ac_qos { __le16 cw_min; __le16 cw_max; @@ -388,6 +434,9 @@ struct iwl_ac_qos { /* number of Access categories (AC) (EDCA), queues 0..3 */ #define AC_NUM 4 +/* + * REPLY_QOS_PARAM = 0x13 (command, has simple generic response) + */ struct iwl_qosparam_cmd { __le32 qos_flags; struct iwl_ac_qos ac[AC_NUM]; @@ -457,9 +506,6 @@ enum { #define RATE_MCS_ANT_B_MSK 0x8000 #define RATE_MCS_ANT_AB_MSK 0xc000 -/* - * Add/Modify Station Command & Response - */ struct iwl_keyinfo { __le16 key_flags; u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ @@ -477,6 +523,9 @@ struct sta_id_modify { __le16 reserved2; } __attribute__ ((packed)); +/* + * REPLY_ADD_STA = 0x18 (command) + */ struct iwl_addsta_cmd { u8 mode; u8 reserved[3]; @@ -498,6 +547,9 @@ struct iwl_addsta_cmd { #endif } __attribute__ ((packed)); +/* + * REPLY_ADD_STA = 0x18 (response) + */ struct iwl_add_sta_resp { u8 status; } __attribute__ ((packed)); @@ -506,7 +558,7 @@ struct iwl_add_sta_resp { /****************************************************************************** * (4) - * Rx Commands & Responses: + * Rx Responses: * *****************************************************************************/ @@ -556,16 +608,23 @@ struct iwl_rx_frame_end { __le32 beacon_timestamp; } __attribute__ ((packed)); -/* NOTE: DO NOT dereference from casts to this structure +/* + * REPLY_3945_RX = 0x1b (response only, not a command) + * + * NOTE: DO NOT dereference from casts to this structure * It is provided only for calculating minimum data set size. * The actual offsets of the hdr and end are dynamic based on - * stats.phy_count */ + * stats.phy_count + */ struct iwl_rx_frame { struct iwl_rx_frame_stats stats; struct iwl_rx_frame_hdr hdr; struct iwl_rx_frame_end end; } __attribute__ ((packed)); +/* + * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command) + */ struct iwl_compressed_ba_resp { __le32 sta_addr_lo32; __le16 sta_addr_hi16; @@ -634,6 +693,9 @@ struct iwl_dram_scratch { __le16 reserved; } __attribute__ ((packed)); +/* + * REPLY_TX = 0x1c (command) + */ struct iwl_tx_cmd { __le16 len; __le16 next_frame_len; @@ -688,8 +750,32 @@ struct iwl_tx_cmd { struct ieee80211_hdr hdr[0]; } __attribute__ ((packed)); -/* - * TX command response status +/* TX command response is sent after *all* transmission attempts. + * + * NOTES: + * + * TX_STATUS_FAIL_NEXT_FRAG + * + * If the fragment flag in the MAC header for the frame being transmitted + * is set and there is insufficient time to transmit the next frame, the + * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'. + * + * TX_STATUS_FIFO_UNDERRUN + * + * Indicates the host did not provide bytes to the FIFO fast enough while + * a TX was in progress. + * + * TX_STATUS_FAIL_MGMNT_ABORT + * + * This status is only possible if the ABORT ON MGMT RX parameter was + * set to true with the TX command. + * + * If the MSB of the status parameter is set then an abort sequence is + * required. This sequence consists of the host activating the TX Abort + * control line, and then waiting for the TX Abort command response. This + * indicates that a the device is no longer in a transmit state, and that the + * command FIFO has been cleared. The host must then deactivate the TX Abort + * control line. Receiving is still allowed in this case. */ enum { TX_STATUS_SUCCESS = 0x01, @@ -762,6 +848,9 @@ enum { #define AGG_TX_STATE_SEQ_NUM_POS 16 #define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000 +/* + * REPLY_TX = 0x1c (response) + */ #if IWL == 4965 struct iwl_tx_resp { u8 frame_count; /* 1 no aggregation, >1 aggregation */ @@ -787,49 +876,11 @@ struct iwl_tx_resp { } __attribute__ ((packed)); #endif - -/* TX command response is sent after *all* transmission attempts. - * - * NOTES: - * - * TX_STATUS_FAIL_NEXT_FRAG - * - * If the fragment flag in the MAC header for the frame being transmitted - * is set and there is insufficient time to transmit the next frame, the - * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'. - * - * TX_STATUS_FIFO_UNDERRUN - * - * Indicates the host did not provide bytes to the FIFO fast enough while - * a TX was in progress. - * - * TX_STATUS_FAIL_MGMNT_ABORT - * - * This status is only possible if the ABORT ON MGMT RX parameter was - * set to true with the TX command. - * - * If the MSB of the status parameter is set then an abort sequence is - * required. This sequence consists of the host activating the TX Abort - * control line, and then waiting for the TX Abort command response. This - * indicates that a the device is no longer in a transmit state, and that the - * command FIFO has been cleared. The host must then deactivate the TX Abort - * control line. Receiving is still allowed in this case. - */ - -struct iwl_tx_power { - u8 tx_gain; /* gain for analog radio */ - u8 dsp_atten; /* gain for DSP */ -} __attribute__ ((packed)); - +#if IWL == 3945 /* - * Tx Power Table Command + * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response) + * 3945 Tx Power Table Command */ -struct iwl_power_per_rate { - u8 rate; /* plcp */ - struct iwl_tx_power tpc; - u8 reserved; -} __attribute__ ((packed)); - struct iwl_txpowertable_cmd { u8 band; u8 reserved; @@ -837,6 +888,22 @@ struct iwl_txpowertable_cmd { struct iwl_power_per_rate power[IWL_MAX_RATES]; } __attribute__ ((packed)); +#elif IWL == 4965 +/* + * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response) + * 4965 Tx Power Table Command + */ +struct iwl_tx_power_table_cmd { + u8 band; + u8 channel_normal_width; + __le16 channel; + struct iwl_tx_power_db tx_power; +} __attribute__ ((packed)); + +#endif + + +#if IWL == 3945 struct iwl_rate_scaling_info { __le16 rate_n_flags; u8 try_cnt; @@ -846,6 +913,8 @@ struct iwl_rate_scaling_info { /** * struct iwl_rate_scaling_cmd - Rate Scaling Command & Response * + * REPLY_RATE_SCALE = 0x47 (command, has simple generic response) + * * NOTE: The table of rates passed to the uCode via the * RATE_SCALE command sets up the corresponding order of * rates used for all related commands, including rate @@ -862,6 +931,52 @@ struct iwl_rate_scaling_cmd { struct iwl_rate_scaling_info table[IWL_MAX_RATES]; } __attribute__ ((packed)); +#elif IWL == 4965 + +/*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */ +#define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1<<0) + +#define LINK_QUAL_AC_NUM AC_NUM +#define LINK_QUAL_MAX_RETRY_NUM 16 + +#define LINK_QUAL_ANT_A_MSK (1<<0) +#define LINK_QUAL_ANT_B_MSK (1<<1) +#define LINK_QUAL_ANT_MSK (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK) + +struct iwl_link_qual_general_params { + u8 flags; + u8 mimo_delimiter; + u8 single_stream_ant_msk; + u8 dual_stream_ant_msk; + u8 start_rate_index[LINK_QUAL_AC_NUM]; +} __attribute__ ((packed)); + +struct iwl_link_qual_agg_params { + __le16 agg_time_limit; + u8 agg_dis_start_th; + u8 agg_frame_cnt_limit; + __le32 reserved; +} __attribute__ ((packed)); + +/* + * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response) + */ +struct iwl_link_quality_cmd { + u8 sta_id; + u8 reserved1; + __le16 control; + struct iwl_link_qual_general_params general_params; + struct iwl_link_qual_agg_params agg_params; + struct { + __le32 rate_n_flags; + } rs_table[LINK_QUAL_MAX_RETRY_NUM]; + __le32 reserved2; +} __attribute__ ((packed)); +#endif + +/* + * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) + */ struct iwl_bt_cmd { u8 flags; u8 lead_time; @@ -896,6 +1011,9 @@ struct iwl_measure_channel { __le16 reserved; } __attribute__ ((packed)); +/* + * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command) + */ struct iwl_spectrum_cmd { __le16 len; /* number of bytes starting from token */ u8 token; /* token id */ @@ -912,6 +1030,9 @@ struct iwl_spectrum_cmd { struct iwl_measure_channel channels[10]; } __attribute__ ((packed)); +/* + * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response) + */ struct iwl_spectrum_resp { u8 token; u8 id; /* id of the prior command replaced, or 0xff */ @@ -959,6 +1080,9 @@ enum iwl_measure_type { IWL_MEASURE_IDLE = (1 << 7), }; +/* + * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command) + */ struct iwl_spectrum_notification { u8 id; /* measurement id -- 0 or 1 */ u8 token; @@ -982,12 +1106,6 @@ struct iwl_spectrum_notification { __le32 status; /* see iwl_measurement_status */ } __attribute__ ((packed)); -struct iwl_csa_notification { - __le16 band; - __le16 channel; - __le32 status; /* 0 - OK, 1 - fail */ -} __attribute__ ((packed)); - /****************************************************************************** * (7) * Power Management Commands, Responses, Notifications: @@ -998,6 +1116,8 @@ struct iwl_csa_notification { * struct iwl_powertable_cmd - Power Table Command * @flags: See below: * + * POWER_TABLE_CMD = 0x77 (command, has simple generic response) + * * PM allow: * bit 0 - '0' Driver not allow power management * '1' Driver allow PM (use rest of parameters) @@ -1052,6 +1172,10 @@ struct iwl_powertable_cmd { } __attribute__ ((packed)); #endif +/* + * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command) + * 3945 and 4965 identical. + */ struct iwl_sleep_notification { u8 pm_sleep_mode; u8 pm_wakeup_src; @@ -1061,6 +1185,7 @@ struct iwl_sleep_notification { __le32 bcon_timer; } __attribute__ ((packed)); +/* Sleep states. 3945 and 4965 identical. */ enum { IWL_PM_NO_SLEEP = 0, IWL_PM_SLP_MAC = 1, @@ -1076,12 +1201,18 @@ enum { }; /* - * card_state Command and Notification + * REPLY_CARD_STATE_CMD = 0xa0 (command, has simple generic response) */ +#define CARD_STATE_CMD_DISABLE 0x00 /* Put card to sleep */ +#define CARD_STATE_CMD_ENABLE 0x01 /* Wake up card */ +#define CARD_STATE_CMD_HALT 0x02 /* Power down permanently */ +struct iwl_card_state_cmd { + __le32 status; /* CARD_STATE_CMD_* request new power state */ +} __attribute__ ((packed)); -#define CARD_STATE_CMD_DISABLE 0x00 -#define CARD_STATE_CMD_ENABLE 0x01 - +/* + * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command) + */ struct iwl_card_state_notif { __le32 flags; } __attribute__ ((packed)); @@ -1104,14 +1235,13 @@ struct iwl_ct_kill_config { *****************************************************************************/ struct iwl_scan_channel { - u8 type; /* type is defined as: * 0:0 active (0 - passive) * 1:4 SSID direct * If 1 is set then corresponding SSID IE is transmitted in probe - * 5:6 reserved - * 7:7 Narrow + * 5:7 reserved */ + u8 type; u8 channel; struct iwl_tx_power tpc; __le16 active_dwell; @@ -1127,8 +1257,11 @@ struct iwl_ssid_ie { #define PROBE_OPTION_MAX 0x4 #define TX_CMD_LIFE_TIME_INFINITE __constant_cpu_to_le32(0xFFFFFFFF) #define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1) - #define IWL_MAX_SCAN_SIZE 1024 + +/* + * REPLY_SCAN_CMD = 0x80 (command) + */ struct iwl_scan_cmd { __le16 len; u8 reserved0; @@ -1173,10 +1306,16 @@ struct iwl_scan_cmd { /* complete notification statuses */ #define ABORT_STATUS 0x2 +/* + * REPLY_SCAN_CMD = 0x80 (response) + */ struct iwl_scanreq_notification { - __le32 status; + __le32 status; /* 1: okay, 2: cannot fulfill request */ } __attribute__ ((packed)); +/* + * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command) + */ struct iwl_scanstart_notification { __le32 tsf_low; __le32 tsf_high; @@ -1191,6 +1330,9 @@ struct iwl_scanstart_notification { #define MEASURE_OWNER_STATUS 0x2; #define NUMBER_OF_STATISTICS 1 /* first __le32 is good CRC */ +/* + * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command) + */ struct iwl_scanresults_notification { u8 channel; u8 band; @@ -1200,6 +1342,9 @@ struct iwl_scanresults_notification { __le32 statistics[NUMBER_OF_STATISTICS]; } __attribute__ ((packed)); +/* + * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command) + */ struct iwl_scancomplete_notification { u8 scanned_channels; u8 status; @@ -1217,7 +1362,7 @@ struct iwl_scancomplete_notification { *****************************************************************************/ /* - * Tx Beacon Command & Response + * BEACON_NOTIFICATION = 0x90 (notification only, not a command) */ struct iwl_beacon_notif { struct iwl_tx_resp beacon_notify_hdr; @@ -1226,6 +1371,9 @@ struct iwl_beacon_notif { __le32 ibss_mgr_status; } __attribute__ ((packed)); +/* + * REPLY_TX_BEACON = 0x91 (command, has simple generic response) + */ struct iwl_tx_beacon_cmd { struct iwl_tx_cmd tx; __le16 tim_idx; @@ -1419,6 +1567,42 @@ struct statistics_general { #endif } __attribute__ ((packed)); +/* + * REPLY_STATISTICS_CMD = 0x9c, + * 3945 and 4965 identical. + * + * This command triggers an immediate response containing uCode statistics. + * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below. + * + * If the CLEAR_STATS configuration flag is set, uCode will clear its + * internal copy of the statistics (counters) after issuing the response. + * This flag does not affect STATISTICS_NOTIFICATIONs after beacons (see below). + * + * If the DISABLE_NOTIF configuration flag is set, uCode will not issue + * STATISTICS_NOTIFICATIONs after received beacons (see below). This flag + * does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself. + */ +#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */ +#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */ +struct iwl_statistics_cmd { + __le32 configuration_flags; /* IWL_STATS_CONF_* */ +} __attribute__ ((packed)); + +/* + * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command) + * + * By default, uCode issues this notification after receiving a beacon + * while associated. To disable this behavior, set DISABLE_NOTIF flag in the + * REPLY_STATISTICS_CMD 0x9c, above. + * + * Statistics counters continue to increment beacon after beacon, but are + * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD + * 0x9c with CLEAR_STATS bit set (see above). + * + * uCode also issues this notification during scans. uCode clears statistics + * appropriately so that each notification contains statistics for only the + * one channel that has just been scanned. + */ struct iwl_notif_statistics { __le32 flag; struct statistics_rx rx; @@ -1427,6 +1611,9 @@ struct iwl_notif_statistics { } __attribute__ ((packed)); +/* + * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command) + */ /* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row, * then this notification will be sent. */ #define CONSECUTIVE_MISSED_BCONS_TH 20 @@ -1470,12 +1657,18 @@ struct iwl_calibration_cmd { /* * LEDs Command & Response + * REPLY_LEDS_CMD = 0x48 (command, has simple generic response) + * + * 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 iwl_led_cmd { - __le32 interval; - u8 id; - u8 off; - u8 on; + __le32 interval; /* "interval" in uSec */ + u8 id; /* 1: Activity, 2: Link, 3: Tech */ + u8 off; /* # intervals off while blinking; + * "0", with >0 "on" value, turns LED on */ + u8 on; /* # intervals on while blinking; + * "0", regardless of "off", turns LED off */ u8 reserved; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwl-eeprom.h b/drivers/net/wireless/iwl-eeprom.h index 74bc28f..e473c97 100644 --- a/drivers/net/wireless/iwl-eeprom.h +++ b/drivers/net/wireless/iwl-eeprom.h @@ -285,7 +285,7 @@ struct iwl_eeprom { #define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ struct iwl_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ #define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ - __le16 band_5_count; /* abs.ofs: 304 */ + u16 band_5_count; /* abs.ofs: 304 */ #define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ struct iwl_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ diff --git a/drivers/net/wireless/iwl-hw.h b/drivers/net/wireless/iwl-hw.h index fe7cb94..3743cdb 100644 --- a/drivers/net/wireless/iwl-hw.h +++ b/drivers/net/wireless/iwl-hw.h @@ -64,18 +64,19 @@ #define __iwlwifi_hw_h__ /* - * This file defines hardware / uCode API constants, enums, - * and inline functions. + * This file defines hardware constants common to 3945 and 4965. * - * For common usage code where the implementation can be the same - * with the exception of a different value going into a constant - * those constants are defined in this file. + * Device-specific constants are defined in iwl-3945-hw.h and iwl-4965-hw.h, + * although this file contains a few definitions for which the .c + * implementation is the same for 3945 and 4965, except for the value of + * a constant. * - * NOTE: DO NOT PUT IMPLEMENTATION SPECIFIC DECLRATIONS HERE + * uCode API constants are defined in iwl-commands.h. * - * The iwl-*hw.h (and files they include) files should remain OS driver - * implementation independent, declaring only the hardware/uCode API + * NOTE: DO NOT PUT OS IMPLEMENTATION-SPECIFIC DECLARATIONS HERE * + * The iwl-*hw.h (and files they include) files should remain OS/driver + * implementation independent, declaring only the hardware interface. */ /* uCode queue management definitions */ @@ -83,6 +84,7 @@ #define IWL_CMD_FIFO_NUM 4 #define IWL_BACK_QUEUE_FIRST_ID 7 +/* Tx rates */ #define IWL_CCK_RATES 4 #define IWL_OFDM_RATES 8 @@ -94,9 +96,7 @@ #define IWL_MAX_RATES (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES) -/* - * Time constants - */ +/* Time constants */ #define SHORT_SLOT_TIME 9 #define LONG_SLOT_TIME 20 @@ -151,7 +151,115 @@ #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) -/* BSM (Bootstrap State Machine) */ +/** + * BSM (Bootstrap State Machine) + * + * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program + * in special SRAM that does not power down when the embedded control + * processor is sleeping (e.g. for periodic power-saving shutdowns of radio). + * + * When powering back up after sleeps (or during initial uCode load), the BSM + * internally loads the short bootstrap program from the special SRAM into the + * embedded processor's instruction SRAM, and starts the processor so it runs + * the bootstrap program. + * + * This bootstrap program loads (via PCI busmaster DMA) instructions and data + * images for a uCode program from host DRAM locations. The host driver + * indicates DRAM locations and sizes for instruction and data images via the + * four BSM_DRAM_* registers. Once the bootstrap program loads the new program, + * the new program starts automatically. + * + * The uCode used for open-source drivers includes two programs: + * + * 1) Initialization -- performs hardware calibration and sets up some + * internal data, then notifies host via "initialize alive" notification + * (struct iwl_init_alive_resp) that it has completed all of its work. + * After signal from host, it then loads and starts the runtime program. + * The initialization program must be used when initially setting up the + * NIC after loading the driver. + * + * 2) Runtime/Protocol -- performs all normal runtime operations. This + * notifies host via "alive" notification (struct iwl_alive_resp) that it + * is ready to be used. + * + * When initializing the NIC, the host driver does the following procedure: + * + * 1) Load bootstrap program (instructions only, no data image for bootstrap) + * into bootstrap memory. Use dword writes starting at BSM_SRAM_LOWER_BOUND + * + * 2) Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction + * images in host DRAM. + * + * 3) Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked: + * BSM_WR_MEM_SRC_REG = 0 + * BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND + * BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image + * + * 4) Load bootstrap into instruction SRAM: + * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START + * + * 5) Wait for load completion: + * Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0 + * + * 6) Enable future boot loads whenever NIC's power management triggers it: + * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN + * + * 7) Start the NIC by removing all reset bits: + * CSR_RESET = 0 + * + * The bootstrap uCode (already in instruction SRAM) loads initialization + * uCode. Initialization uCode performs data initialization, sends + * "initialize alive" notification to host, and waits for a signal from + * host to load runtime code. + * + * 4) Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction + * images in host DRAM. The last register loaded must be the instruction + * bytecount register ("1" in MSbit tells initialization uCode to load + * the runtime uCode): + * BSM_DRAM_INST_BYTECOUNT_REG = bytecount | BSM_DRAM_INST_LOAD + * + * 5) Wait for "alive" notification, then issue normal runtime commands. + * + * Data caching during power-downs: + * + * Just before the embedded controller powers down (e.g for automatic + * power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA) + * a current snapshot of the embedded processor's data SRAM into host DRAM. + * This caches the data while the embedded processor's memory is powered down. + * Location and size are controlled by BSM_DRAM_DATA_* registers. + * + * NOTE: Instruction SRAM does not need to be saved, since that doesn't + * change during operation; the original image (from uCode distribution + * file) can be used for reload. + * + * When powering back up, the BSM loads the bootstrap program. Bootstrap looks + * at the BSM_DRAM_* registers, which now point to the runtime instruction + * image and the cached (modified) runtime data (*not* the initialization + * uCode). Bootstrap reloads these runtime images into SRAM, and restarts the + * uCode from where it left off before the power-down. + * + * NOTE: Initialization uCode does *not* run as part of the save/restore + * procedure. + * + * This save/restore method is mostly for autonomous power management during + * normal operation (result of POWER_TABLE_CMD). Platform suspend/resume and + * RFKILL should use complete restarts (with total re-initialization) of uCode, + * allowing total shutdown (including BSM memory). + * + * Note that, during normal operation, the host DRAM that held the initial + * startup data for the runtime code is now being used as a backup data cache + * for modified data! If you need to completely re-initialize the NIC, make + * sure that you use the runtime data image from the uCode distribution file, + * not the modified/saved runtime data. You may want to store a separate + * "clean" runtime data image in DRAM to avoid disk reads of distribution file. + */ + +/* BSM bit fields */ +#define BSM_WR_CTRL_REG_BIT_START (0x80000000) /* start boot load now */ +#define BSM_WR_CTRL_REG_BIT_START_EN (0x40000000) /* enable boot after pwrup*/ +#define BSM_DRAM_INST_LOAD (0x80000000) /* start program load now */ + +/* BSM addresses */ #define BSM_BASE (CSR_BASE + 0x3400) #define BSM_WR_CTRL_REG (BSM_BASE + 0x000) /* ctl and status */ @@ -160,19 +268,25 @@ #define BSM_WR_DWCOUNT_REG (BSM_BASE + 0x00C) /* bytes */ #define BSM_WR_STATUS_REG (BSM_BASE + 0x010) /* bit 0: 1 == done */ -/* pointers and size regs for bootstrap load and data SRAM save */ +/* + * Pointers and size regs for bootstrap load and data SRAM save/restore. + * NOTE: 3945 pointers use bits 31:0 of DRAM address. + * 4965 pointers use bits 35:4 of DRAM address. + */ #define BSM_DRAM_INST_PTR_REG (BSM_BASE + 0x090) #define BSM_DRAM_INST_BYTECOUNT_REG (BSM_BASE + 0x094) #define BSM_DRAM_DATA_PTR_REG (BSM_BASE + 0x098) #define BSM_DRAM_DATA_BYTECOUNT_REG (BSM_BASE + 0x09C) -/* BSM special memory, stays powered during power-save sleeps */ +/* + * BSM special memory, stays powered on during power-save sleeps. + * Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1) + */ #define BSM_SRAM_LOWER_BOUND (CSR_BASE + 0x3800) -#define BSM_SRAM_SIZE (1024) +#define BSM_SRAM_SIZE (1024) /* bytes */ -/* DBG MON */ -/* SCD */ +/* SCD (Scheduler) */ #define SCD_BASE (CSR_BASE + 0x2E00) #define SCD_MODE_REG (SCD_BASE + 0x000) @@ -183,7 +297,7 @@ #define SCD_SBYP_MODE_1_REG (SCD_BASE + 0x02C) #define SCD_SBYP_MODE_2_REG (SCD_BASE + 0x030) -/*=== HBUS (Host-side bus) ===*/ +/*=== HBUS (Host-side Bus) ===*/ #define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) #define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) @@ -194,7 +308,8 @@ #define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) -/*=== FH (data Flow handler) ===*/ + +/*=== FH (data Flow Handler) ===*/ #define FH_CBCC_TABLE (FH_BASE+0x140) #define FH_TFDB_TABLE (FH_BASE+0x180) @@ -347,10 +462,6 @@ #define APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN (0x00000000) #define APMG_PS_CTRL_REG_VAL_POWER_SRC_VAUX (0x01000000) -/* BSM (bootstrap state machine) */ -#define BSM_WR_CTRL_REG_BIT_START (0x80000000) /* start boot load now */ -#define BSM_WR_CTRL_REG_BIT_START_EN (0x40000000) /* enable boot after pwrup*/ - /* DBM */ #define ALM_FH_SRVC_CHNL (6) diff --git a/drivers/net/wireless/iwl-io.h b/drivers/net/wireless/iwl-io.h index 5df7e36..f293702 100644 --- a/drivers/net/wireless/iwl-io.h +++ b/drivers/net/wireless/iwl-io.h @@ -166,7 +166,7 @@ static inline int _iwl_grab_restricted_access(struct iwl_priv *priv) if (atomic_read(&priv->restrict_refcnt)) return 0; #endif - if (test_bit(STATUS_RF_KILL_HW, &priv->status) | + if (test_bit(STATUS_RF_KILL_HW, &priv->status) || test_bit(STATUS_RF_KILL_SW, &priv->status)) { IWL_WARNING("WARNING: Requesting MAC access during RFKILL " "wakes up NIC\n"); @@ -190,14 +190,13 @@ static inline int _iwl_grab_restricted_access(struct iwl_priv *priv) CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50); if (rc < 0) { IWL_ERROR("MAC is in deep sleep!\n"); - rc = -EIO; - goto out; + return -EIO; } + #ifdef CONFIG_IWLWIFI_DEBUG atomic_inc(&priv->restrict_refcnt); #endif -out: - return rc; + return 0; } #ifdef CONFIG_IWLWIFI_DEBUG diff --git a/drivers/net/wireless/iwl-priv.h b/drivers/net/wireless/iwl-priv.h index 964c8fe..c9cb11e 100644 --- a/drivers/net/wireless/iwl-priv.h +++ b/drivers/net/wireless/iwl-priv.h @@ -91,7 +91,8 @@ struct iwl_priv { u8 only_active_channel; /* spinlock */ - spinlock_t lock; + spinlock_t lock; /* protect general shared data */ + spinlock_t hcmd_lock; /* protect hcmd */ struct mutex mutex; /* basic pci-network driver stuff */ @@ -261,6 +262,7 @@ struct iwl_priv { struct work_struct auth_work; struct work_struct report_work; struct work_struct request_scan; + struct work_struct beacon_update; struct tasklet_struct irq_tasklet; diff --git a/drivers/net/wireless/iwlwifi.h b/drivers/net/wireless/iwlwifi.h index dc451bd..fcf0197 100644 --- a/drivers/net/wireless/iwlwifi.h +++ b/drivers/net/wireless/iwlwifi.h @@ -80,7 +80,7 @@ extern int iwl_param_disable; extern int iwl_param_antenna; extern int iwl_param_hwcrypto; extern int iwl_param_qos_enable; - +extern int iwl_param_queues_num; enum iwl_antenna { IWL_ANTENNA_DIVERSITY, @@ -192,7 +192,7 @@ struct iwl_tx_queue { #define IWL_TX_QUEUE_HCCA_1 5 #define IWL_TX_QUEUE_HCCA_2 6 #define IWL_TX_QUEUE_NONE 7 -#define IWL_MAX_NUM_QUEUES 16 +#define IWL_MIN_NUM_QUEUES 4 /* Power management (not Tx power) structures */ @@ -292,7 +292,6 @@ struct iwl_cmd { struct iwl_tx_cmd tx; struct iwl_tx_beacon_cmd tx_beacon; struct iwl_rxon_assoc_cmd rxon_assoc; - struct iwl_rate_scaling_cmd rate_scale; u8 *indirect; u8 payload[360]; } __attribute__ ((packed)) cmd; @@ -531,7 +530,7 @@ struct iwl_ibss_seq { }; struct iwl_driver_hw_info { - u16 max_queue_number; + u16 max_txq_num; u16 ac_queue_count; u32 rx_buffer_size; u16 tx_cmd_len;