{
/* These items are only settable from the full RXON command */
- if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ||
+ if (!(iwl_is_associated(priv)) ||
compare_ether_addr(priv->staging_rxon.bssid_addr,
priv->active_rxon.bssid_addr) ||
compare_ether_addr(priv->staging_rxon.node_addr,
/* cast away the const for active_rxon in this function */
struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
DECLARE_MAC_BUF(mac);
- int rc = 0;
+ int ret;
+ bool new_assoc =
+ !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
if (!iwl_is_alive(priv))
- return -1;
+ return -EBUSY;
/* always get timestamp with Rx frame */
priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
+ /* allow CTS-to-self if possible. this is relevant only for
+ * 5000, but will not damage 4965 */
+ priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
- rc = iwl4965_check_rxon_cmd(&priv->staging_rxon);
- if (rc) {
+ ret = iwl4965_check_rxon_cmd(&priv->staging_rxon);
+ if (ret) {
IWL_ERROR("Invalid RXON configuration. Not committing.\n");
return -EINVAL;
}
* iwl4965_rxon_assoc_cmd which is used to reconfigure filter
* and other flags for the current radio configuration. */
if (!iwl4965_full_rxon_required(priv)) {
- rc = iwl_send_rxon_assoc(priv);
- if (rc) {
- IWL_ERROR("Error setting RXON_ASSOC "
- "configuration (%d).\n", rc);
- return rc;
+ ret = iwl_send_rxon_assoc(priv);
+ if (ret) {
+ IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret);
+ return ret;
}
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
-
return 0;
}
* an RXON_ASSOC and the new config wants the associated mask enabled,
* we must clear the associated from the active configuration
* before we apply the new config */
- if (iwl_is_associated(priv) &&
- (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
+ if (iwl_is_associated(priv) && new_assoc) {
IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+ ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
sizeof(struct iwl_rxon_cmd),
&priv->active_rxon);
/* If the mask clearing failed then we set
* active_rxon back to what it was previously */
- if (rc) {
+ if (ret) {
active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
- IWL_ERROR("Error clearing ASSOC_MSK on current "
- "configuration (%d).\n", rc);
- return rc;
+ IWL_ERROR("Error clearing ASSOC_MSK (%d)\n", ret);
+ return ret;
}
}
"* with%s RXON_FILTER_ASSOC_MSK\n"
"* channel = %d\n"
"* bssid = %s\n",
- ((priv->staging_rxon.filter_flags &
- RXON_FILTER_ASSOC_MSK) ? "" : "out"),
+ (new_assoc ? "" : "out"),
le16_to_cpu(priv->staging_rxon.channel),
print_mac(mac, priv->staging_rxon.bssid_addr));
iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
- /* Apply the new configuration */
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+
+ /* Apply the new configuration
+ * RXON unassoc clears the station table in uCode, send it before
+ * we add the bcast station. If assoc bit is set, we will send RXON
+ * after having added the bcast and bssid station.
+ */
+ if (!new_assoc) {
+ ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
- if (rc) {
- IWL_ERROR("Error setting new configuration (%d).\n", rc);
- return rc;
+ if (ret) {
+ IWL_ERROR("Error setting new RXON (%d)\n", ret);
+ return ret;
+ }
+ memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
}
- iwl_remove_station(priv, iwl_bcast_addr, 0);
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
if (!priv->error_recovering)
priv->start_calib = 0;
iwl_init_sensitivity(priv);
- memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
-
/* If we issue a new RXON command which required a tune then we must
* send a new TXPOWER command or we won't be able to Tx any frames */
- rc = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
- if (rc) {
- IWL_ERROR("Error sending TX power (%d).\n", rc);
- return rc;
+ ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+ if (ret) {
+ IWL_ERROR("Error sending TX power (%d)\n", ret);
+ return ret;
}
/* Add the broadcast address so we can send broadcast frames */
if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
- IWL_INVALID_STATION) {
+ IWL_INVALID_STATION) {
IWL_ERROR("Error adding BROADCAST address for transmit.\n");
return -EIO;
}
/* If we have set the ASSOC_MSK and we are in BSS mode then
* add the IWL_AP_ID to the station rate table */
- if (iwl_is_associated(priv) &&
- (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
- if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
- == IWL_INVALID_STATION) {
- IWL_ERROR("Error adding AP address for transmit.\n");
- return -EIO;
+ if (new_assoc) {
+ if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+ ret = iwl_rxon_add_station(priv,
+ priv->active_rxon.bssid_addr, 1);
+ if (ret == IWL_INVALID_STATION) {
+ IWL_ERROR("Error adding AP address for TX.\n");
+ return -EIO;
+ }
+ priv->assoc_station_added = 1;
+ if (priv->default_wep_key &&
+ iwl_send_static_wepkey_cmd(priv, 0))
+ IWL_ERROR("Could not send WEP static key.\n");
}
- priv->assoc_station_added = 1;
- if (priv->default_wep_key &&
- iwl_send_static_wepkey_cmd(priv, 0))
- IWL_ERROR("Could not send WEP static key.\n");
+
+ /* Apply the new configuration
+ * RXON assoc doesn't clear the station table in uCode,
+ */
+ ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
+ sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
+ if (ret) {
+ IWL_ERROR("Error setting new RXON (%d)\n", ret);
+ return ret;
+ }
+ memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
}
return 0;
sizeof(struct iwl4965_bt_cmd), &bt_cmd);
}
-/*
- * CARD_STATE_CMD
- *
- * Use: Sets the device's internal card state to enable, disable, or halt
- *
- * When in the 'enable' state the card operates as normal.
- * When in the 'disable' state, the card enters into a low power mode.
- * When in the 'halt' state, the card is shut down and must be fully
- * restarted to come back on.
- */
-static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
-{
- struct iwl_host_cmd cmd = {
- .id = REPLY_CARD_STATE_CMD,
- .len = sizeof(u32),
- .data = &flags,
- .meta.flags = meta_flag,
- };
-
- return iwl_send_cmd(priv, &cmd);
-}
-
static void iwl_clear_free_frames(struct iwl_priv *priv)
{
struct list_head *element;
}
}
-int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
-{
- /* Filter incoming packets to determine if they are targeted toward
- * this network, discarding packets coming from ourselves */
- switch (priv->iw_mode) {
- case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */
- /* packets from our adapter are dropped (echo) */
- if (!compare_ether_addr(header->addr2, priv->mac_addr))
- return 0;
- /* {broad,multi}cast packets to our IBSS go through */
- if (is_multicast_ether_addr(header->addr1))
- return !compare_ether_addr(header->addr3, priv->bssid);
- /* packets to our adapter go through */
- return !compare_ether_addr(header->addr1, priv->mac_addr);
- case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
- /* packets from our adapter are dropped (echo) */
- if (!compare_ether_addr(header->addr3, priv->mac_addr))
- return 0;
- /* {broad,multi}cast packets to our BSS go through */
- if (is_multicast_ether_addr(header->addr1))
- return !compare_ether_addr(header->addr2, priv->bssid);
- /* packets to our adapter go through */
- return !compare_ether_addr(header->addr1, priv->mac_addr);
- default:
- break;
- }
-
- return 1;
-}
-
-static void iwl4965_sequence_reset(struct iwl_priv *priv)
-{
- /* Reset ieee stats */
-
- /* We don't reset the net_device_stats (ieee->stats) on
- * re-association */
-
- priv->last_seq_num = -1;
- priv->last_frag_num = -1;
- priv->last_packet_time = 0;
-
- iwl_scan_cancel(priv);
-}
-
#define MAX_UCODE_BEACON_INTERVAL 4096
#define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA)
#endif
ch_info = iwl_get_channel_info(priv, priv->band,
- le16_to_cpu(priv->staging_rxon.channel));
+ le16_to_cpu(priv->active_rxon.channel));
if (!ch_info)
ch_info = &priv->channel_info[0];
{
priv->iw_mode = mode;
- /* init channel/phymode to values given at driver init */
- iwl_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
-
iwl4965_connection_init_rx_config(priv);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
/* dont commit rxon if rf-kill is on*/
if (!iwl_is_ready_rf(priv))
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}
-int iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
-{
- unsigned long flags;
-
- if (!!disable_radio == test_bit(STATUS_RF_KILL_SW, &priv->status))
- return 0;
-
- IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO %s\n",
- disable_radio ? "OFF" : "ON");
-
- if (disable_radio) {
- iwl_scan_cancel(priv);
- /* FIXME: This is a workaround for AP */
- if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
- spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
- CSR_UCODE_SW_BIT_RFKILL);
- spin_unlock_irqrestore(&priv->lock, flags);
- /* call the host command only if no hw rf-kill set */
- if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
- iwl_is_ready(priv))
- iwl4965_send_card_state(priv,
- CARD_STATE_CMD_DISABLE,
- 0);
- set_bit(STATUS_RF_KILL_SW, &priv->status);
-
- /* make sure mac80211 stop sending Tx frame */
- if (priv->mac80211_registered)
- ieee80211_stop_queues(priv->hw);
- }
- return 0;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
- clear_bit(STATUS_RF_KILL_SW, &priv->status);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* wake up ucode */
- msleep(10);
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl_read32(priv, CSR_UCODE_DRV_GP1);
- if (!iwl_grab_nic_access(priv))
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
- IWL_DEBUG_RF_KILL("Can not turn radio back on - "
- "disabled by HW switch\n");
- return 0;
- }
-
- queue_work(priv->workqueue, &priv->restart);
- return 1;
-}
-
-#define IWL_PACKET_RETRY_TIME HZ
-
-int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
-{
- u16 sc = le16_to_cpu(header->seq_ctrl);
- u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
- u16 frag = sc & IEEE80211_SCTL_FRAG;
- u16 *last_seq, *last_frag;
- unsigned long *last_time;
-
- switch (priv->iw_mode) {
- case IEEE80211_IF_TYPE_IBSS:{
- struct list_head *p;
- struct iwl4965_ibss_seq *entry = NULL;
- u8 *mac = header->addr2;
- int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
-
- __list_for_each(p, &priv->ibss_mac_hash[index]) {
- entry = list_entry(p, struct iwl4965_ibss_seq, list);
- if (!compare_ether_addr(entry->mac, mac))
- break;
- }
- if (p == &priv->ibss_mac_hash[index]) {
- entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
- if (!entry) {
- IWL_ERROR("Cannot malloc new mac entry\n");
- return 0;
- }
- memcpy(entry->mac, mac, ETH_ALEN);
- entry->seq_num = seq;
- entry->frag_num = frag;
- entry->packet_time = jiffies;
- list_add(&entry->list, &priv->ibss_mac_hash[index]);
- return 0;
- }
- last_seq = &entry->seq_num;
- last_frag = &entry->frag_num;
- last_time = &entry->packet_time;
- break;
- }
- case IEEE80211_IF_TYPE_STA:
- last_seq = &priv->last_seq_num;
- last_frag = &priv->last_frag_num;
- last_time = &priv->last_packet_time;
- break;
- default:
- return 0;
- }
- if ((*last_seq == seq) &&
- time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
- if (*last_frag == frag)
- goto drop;
- if (*last_frag + 1 != frag)
- /* out-of-order fragment */
- goto drop;
- } else
- *last_seq = seq;
-
- *last_frag = frag;
- *last_time = jiffies;
- return 0;
-
- drop:
- return 1;
-}
-
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
#include "iwl-spectrum.h"
wake_up_interruptible(&priv->wait_command_queue);
}
-/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
- * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
-static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
-{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- priv->last_phy_res[0] = 1;
- memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
- sizeof(struct iwl4965_rx_phy_res));
-}
-
/**
* iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
*
* This function chains into the hardware specific files for them to setup
* any hardware specific handlers as well.
*/
-static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
+static void iwl_setup_rx_handlers(struct iwl_priv *priv)
{
priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
* statistics request from the host as well as for the periodic
* statistics notifications (after received beacons) from the uCode.
*/
- priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics;
- priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics;
+ priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics;
+ priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
iwl_setup_rx_scan_handlers(priv);
priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
iwl_rx_missed_beacon_notif;
/* Rx handlers */
- priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
- priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx;
+ priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy;
+ priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx;
+ /* block ack */
+ priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba;
/* Set up hardware specific Rx handlers */
priv->cfg->ops->lib->rx_handler_setup(priv);
}
priv->rxq.read = i;
iwl_rx_queue_restock(priv);
}
-/* Convert linear signal-to-noise ratio into dB */
-static u8 ratio2dB[100] = {
-/* 0 1 2 3 4 5 6 7 8 9 */
- 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
- 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
- 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
- 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
- 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
- 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
- 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
- 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
- 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
- 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */
-};
-
-/* Calculates a relative dB value from a ratio of linear
- * (i.e. not dB) signal levels.
- * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
-int iwl4965_calc_db_from_ratio(int sig_ratio)
-{
- /* 1000:1 or higher just report as 60 dB */
- if (sig_ratio >= 1000)
- return 60;
-
- /* 100:1 or higher, divide by 10 and use table,
- * add 20 dB to make up for divide by 10 */
- if (sig_ratio >= 100)
- return (20 + (int)ratio2dB[sig_ratio/10]);
-
- /* We shouldn't see this */
- if (sig_ratio < 1)
- return 0;
-
- /* Use table for ratios 1:1 - 99:1 */
- return (int)ratio2dB[sig_ratio];
-}
-
-#define PERFECT_RSSI (-20) /* dBm */
-#define WORST_RSSI (-95) /* dBm */
-#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
-
-/* Calculate an indication of rx signal quality (a percentage, not dBm!).
- * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
- * about formulas used below. */
-int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
-{
- int sig_qual;
- int degradation = PERFECT_RSSI - rssi_dbm;
-
- /* If we get a noise measurement, use signal-to-noise ratio (SNR)
- * as indicator; formula is (signal dbm - noise dbm).
- * SNR at or above 40 is a great signal (100%).
- * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
- * Weakest usable signal is usually 10 - 15 dB SNR. */
- if (noise_dbm) {
- if (rssi_dbm - noise_dbm >= 40)
- return 100;
- else if (rssi_dbm < noise_dbm)
- return 0;
- sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
-
- /* Else use just the signal level.
- * This formula is a least squares fit of data points collected and
- * compared with a reference system that had a percentage (%) display
- * for signal quality. */
- } else
- sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
- (15 * RSSI_RANGE + 62 * degradation)) /
- (RSSI_RANGE * RSSI_RANGE);
-
- if (sig_qual > 100)
- sig_qual = 100;
- else if (sig_qual < 1)
- sig_qual = 0;
-
- return sig_qual;
-}
#ifdef CONFIG_IWLWIFI_DEBUG
static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n",
hw_rf_kill ? "disable radio":"enable radio");
- /* 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
- * iwl4965_rx_card_state_notif() */
- if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
+ /* driver only loads ucode once setting the interface up.
+ * the driver as well won't allow loading if RFKILL is set
+ * therefore no need to restart the driver from this handler
+ */
+ if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status))
clear_bit(STATUS_RF_KILL_HW, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
- }
handled |= CSR_INT_BIT_RF_KILL;
}
*/
static int iwl4965_read_ucode(struct iwl_priv *priv)
{
- struct iwl4965_ucode *ucode;
+ struct iwl_ucode *ucode;
int ret;
const struct firmware *ucode_raw;
const char *name = priv->cfg->fw_name;
goto restart;
}
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
ret = priv->cfg->ops->lib->alive_notify(priv);
if (ret) {
IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
iwl4965_commit_rxon(priv);
/* At this point, the NIC is initialized and operational */
- iwl4965_rf_kill_ct_config(priv);
+ iwl_rf_kill_ct_config(priv);
iwl_leds_register(priv);
if (priv->error_recovering)
iwl4965_error_recovery(priv);
- iwlcore_low_level_notify(priv, IWLCORE_START_EVT);
+ iwl_power_update_mode(priv, 1);
ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
iwl_leds_unregister(priv);
- iwlcore_low_level_notify(priv, IWLCORE_STOP_EVT);
-
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
/* Unblock any waiting calls */
wake_up_interruptible_all(&priv->wait_command_queue);
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
STATUS_GEO_CONFIGURED |
test_bit(STATUS_IN_SUSPEND, &priv->status) <<
- STATUS_IN_SUSPEND;
+ STATUS_IN_SUSPEND |
+ test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+ STATUS_EXIT_PENDING;
goto exit;
}
test_bit(STATUS_IN_SUSPEND, &priv->status) <<
STATUS_IN_SUSPEND |
test_bit(STATUS_FW_ERROR, &priv->status) <<
- STATUS_FW_ERROR;
+ STATUS_FW_ERROR |
+ test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+ STATUS_EXIT_PENDING;
spin_lock_irqsave(&priv->lock, flags);
iwl_clear_bit(priv, CSR_GP_CNTRL,
if (iwl_read32(priv, CSR_GP_CNTRL) &
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
clear_bit(STATUS_RF_KILL_HW, &priv->status);
- else {
+ else
set_bit(STATUS_RF_KILL_HW, &priv->status);
- if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
- iwl_rfkill_set_hw_state(priv);
- IWL_WARNING("Radio disabled by HW RF Kill switch\n");
- return -ENODEV;
- }
+
+ if (!test_bit(STATUS_IN_SUSPEND, &priv->status) &&
+ iwl_is_rfkill(priv)) {
+ IWL_WARNING("Radio disabled by %s RF Kill switch\n",
+ test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
+ return -ENODEV;
}
- iwl_rfkill_set_hw_state(priv);
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
ret = priv->cfg->ops->lib->alloc_shared_mem(priv);
for (i = 0; i < MAX_HW_RESTARTS; i++) {
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
/* load bootstrap state machine,
* load bootstrap program into processor's memory,
"Kill switch must be turned off for "
"wireless networking to work.\n");
}
- iwl_rfkill_set_hw_state(priv);
-
mutex_unlock(&priv->mutex);
+ iwl_rfkill_set_hw_state(priv);
}
static void iwl4965_bg_set_monitor(struct work_struct *work)
mutex_lock(&priv->mutex);
__iwl4965_up(priv);
mutex_unlock(&priv->mutex);
+ iwl_rfkill_set_hw_state(priv);
}
static void iwl4965_bg_restart(struct work_struct *data)
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_STA:
- iwl4965_rate_scale_init(priv->hw, IWL_AP_ID);
break;
case IEEE80211_IF_TYPE_IBSS:
priv->assoc_id = 1;
iwl_rxon_add_station(priv, priv->bssid, 0);
- iwl4965_rate_scale_init(priv->hw, IWL_STA_ID);
iwl4965_send_beacon_cmd(priv);
break;
break;
}
- iwl4965_sequence_reset(priv);
-
/* Enable Rx differential gain and sensitivity calibrations */
iwl_chain_noise_reset(priv);
priv->start_calib = 1;
*
*****************************************************************************/
-#define UCODE_READY_TIMEOUT (2 * HZ)
+#define UCODE_READY_TIMEOUT (4 * HZ)
static int iwl4965_mac_start(struct ieee80211_hw *hw)
{
mutex_unlock(&priv->mutex);
+ iwl_rfkill_set_hw_state(priv);
+
if (ret)
goto out_release_irq;
/* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
* mac80211 will not be run successfully. */
- if (priv->ucode_type == UCODE_RT) {
- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
- test_bit(STATUS_READY, &priv->status),
- UCODE_READY_TIMEOUT);
- if (!ret) {
- if (!test_bit(STATUS_READY, &priv->status)) {
- IWL_ERROR("START_ALIVE timeout after %dms.\n",
- jiffies_to_msecs(UCODE_READY_TIMEOUT));
- ret = -ETIMEDOUT;
- goto out_release_irq;
- }
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ test_bit(STATUS_READY, &priv->status),
+ UCODE_READY_TIMEOUT);
+ if (!ret) {
+ if (!test_bit(STATUS_READY, &priv->status)) {
+ IWL_ERROR("START_ALIVE timeout after %dms.\n",
+ jiffies_to_msecs(UCODE_READY_TIMEOUT));
+ ret = -ETIMEDOUT;
+ goto out_release_irq;
}
-
- priv->is_open = 1;
}
+
+ priv->is_open = 1;
IWL_DEBUG_MAC80211("leave\n");
return 0;
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
IWL_DEBUG_MAC80211("leave - monitor\n");
- return -1;
+ dev_kfree_skb_any(skb);
+ return 0;
}
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
-
- if (priv->cfg->ops->lib->radio_kill_sw &&
- priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled)) {
+ if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
- mutex_unlock(&priv->mutex);
+ goto out;
}
+ if (!conf->radio_enabled)
+ iwl_radio_kill_sw_disable_radio(priv);
+
if (!iwl_is_ready(priv)) {
IWL_DEBUG_MAC80211("leave - not ready\n");
ret = -EIO;
return;
/* The following should be done only at AP bring up */
- if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) {
+ if (!(iwl_is_associated(priv))) {
/* RXON - unassoc (to set timing command) */
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
* clear sta table, add BCAST sta... */
}
+/* temporary */
+static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
+
static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
return 0;
}
+ if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+ conf->changed & IEEE80211_IFCC_BEACON) {
+ struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+ if (!beacon)
+ return -ENOMEM;
+ rc = iwl4965_mac_beacon_update(hw, beacon);
+ if (rc)
+ return rc;
+ }
+
if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
- (!conf->beacon || !conf->ssid_len)) {
+ (!conf->ssid_len)) {
IWL_DEBUG_MAC80211
("Leaving in AP mode because HostAPD is not ready.\n");
return 0;
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
- priv->ibss_beacon = conf->beacon;
+ priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
}
if (iwl_is_rfkill(priv))
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list)
{
- /*
- * XXX: dummy
- * see also iwl4965_connection_init_rx_config
- */
struct iwl_priv *priv = hw->priv;
- int new_flags = 0;
- if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
- if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
- IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
- IEEE80211_IF_TYPE_MNTR,
- changed_flags, *total_flags);
- /* queue work 'cuz mac80211 is holding a lock which
- * prevents us from issuing (synchronous) f/w cmds */
- queue_work(priv->workqueue, &priv->set_monitor);
- new_flags &= FIF_PROMISC_IN_BSS |
- FIF_OTHER_BSS |
- FIF_ALLMULTI;
- }
+
+ if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
+ IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
+ IEEE80211_IF_TYPE_MNTR,
+ changed_flags, *total_flags);
+ /* queue work 'cuz mac80211 is holding a lock which
+ * prevents us from issuing (synchronous) f/w cmds */
+ queue_work(priv->workqueue, &priv->set_monitor);
}
- *total_flags = new_flags;
+ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
+ FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
return 0;
}
-static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw)
-{
- struct iwl_priv *priv;
-
- priv = hw->priv;
- IWL_DEBUG_MAC80211("enter\n");
- IWL_DEBUG_MAC80211("leave\n");
-
- return 0;
-}
-
static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
- priv->lq_mngr.lq_ready = 0;
spin_lock_irqsave(&priv->lock, flags);
memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
spin_unlock_irqrestore(&priv->lock, flags);
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
+ __le64 timestamp;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
priv->ibss_beacon = skb;
priv->assoc_id = 0;
+ timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+ priv->timestamp = le64_to_cpu(timestamp) + (priv->beacon_int * 1000);
IWL_DEBUG_MAC80211("leave\n");
spin_unlock_irqrestore(&priv->lock, flags);
{
struct iwl_priv *priv = d->driver_data;
struct iwl_alive_resp *palive = &priv->card_alive;
+ ssize_t pos = 0;
+ u16 eeprom_ver;
if (palive->is_valid)
- return sprintf(buf, "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
- "fw type: 0x%01X 0x%01X\n",
+ pos += sprintf(buf + pos,
+ "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
+ "fw type: 0x%01X 0x%01X\n",
palive->ucode_major, palive->ucode_minor,
palive->sw_rev[0], palive->sw_rev[1],
palive->ver_type, palive->ver_subtype);
-
else
- return sprintf(buf, "fw not loaded\n");
+ pos += sprintf(buf + pos, "fw not loaded\n");
+
+ if (priv->eeprom) {
+ eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+ pos += sprintf(buf + pos, "EEPROM version: 0x%x\n",
+ eeprom_ver);
+ } else {
+ pos += sprintf(buf + pos, "EEPROM not initialzed\n");
+ }
+
+ return pos;
}
static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL);
if (!iwl_is_alive(priv))
return -EAGAIN;
- return sprintf(buf, "%d\n", iwl4965_hw_get_temperature(priv));
+ return sprintf(buf, "%d\n", priv->temperature);
}
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
static ssize_t show_channels(struct device *d,
struct device_attribute *attr, char *buf)
{
- /* all this shit doesn't belong into sysfs anyway */
- return 0;
+
+ struct iwl_priv *priv = dev_get_drvdata(d);
+ struct ieee80211_channel *channels = NULL;
+ const struct ieee80211_supported_band *supp_band = NULL;
+ int len = 0, i;
+ int count = 0;
+
+ if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
+ return -EAGAIN;
+
+ supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
+ channels = supp_band->channels;
+ count = supp_band->n_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",
+ ieee80211_frequency_to_channel(
+ channels[i].center_freq),
+ channels[i].max_power,
+ channels[i].flags & IEEE80211_CHAN_RADAR ?
+ " (IEEE 802.11h required)" : "",
+ (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+ || (channels[i].flags &
+ IEEE80211_CHAN_RADAR)) ? "" :
+ ", IBSS",
+ channels[i].flags &
+ IEEE80211_CHAN_PASSIVE_SCAN ?
+ "passive only" : "active/passive");
+
+ supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
+ channels = supp_band->channels;
+ count = supp_band->n_channels;
+
+ 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",
+ ieee80211_frequency_to_channel(
+ channels[i].center_freq),
+ channels[i].max_power,
+ channels[i].flags & IEEE80211_CHAN_RADAR ?
+ " (IEEE 802.11h required)" : "",
+ ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+ || (channels[i].flags &
+ IEEE80211_CHAN_RADAR)) ? "" :
+ ", IBSS",
+ channels[i].flags &
+ IEEE80211_CHAN_PASSIVE_SCAN ?
+ "passive only" : "active/passive");
+
+ return len;
}
static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
- u32 size = sizeof(struct iwl4965_notif_statistics);
+ u32 size = sizeof(struct iwl_notif_statistics);
u32 len = 0, ofs = 0;
u8 *data = (u8 *) & priv->statistics;
int rc = 0;
.get_stats = iwl4965_mac_get_stats,
.get_tx_stats = iwl4965_mac_get_tx_stats,
.conf_tx = iwl4965_mac_conf_tx,
- .get_tsf = iwl4965_mac_get_tsf,
.reset_tsf = iwl4965_mac_reset_tsf,
- .beacon_update = iwl4965_mac_beacon_update,
.bss_info_changed = iwl4965_bss_info_changed,
.ampdu_action = iwl4965_mac_ampdu_action,
.hw_scan = iwl4965_mac_hw_scan
/************************
* 5. Setup HW constants
************************/
- /* Device-specific setup */
- if (priv->cfg->ops->lib->set_hw_params(priv)) {
+ if (iwl_set_hw_params(priv)) {
IWL_ERROR("failed to set hw parameters\n");
goto out_free_eeprom;
}
iwl_setup_deferred_work(priv);
- iwl4965_setup_rx_handlers(priv);
+ iwl_setup_rx_handlers(priv);
/********************
* 9. Conclude
if (err)
IWL_ERROR("failed to create debugfs files\n");
- /* notify iwlcore to init */
- iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT);
+ err = iwl_rfkill_init(priv);
+ if (err)
+ IWL_ERROR("Unable to initialize RFKILL system. "
+ "Ignoring error: %d\n", err);
+ iwl_power_initialize(priv);
return 0;
out_remove_sysfs:
static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
{
struct iwl_priv *priv = pci_get_drvdata(pdev);
- struct list_head *p, *q;
- int i;
unsigned long flags;
if (!priv)
iwl_synchronize_irq(priv);
- /* Free MAC hash list for ADHOC */
- for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
- list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
- list_del(p);
- kfree(list_entry(p, struct iwl4965_ibss_seq, list));
- }
- }
-
- iwlcore_low_level_notify(priv, IWLCORE_REMOVE_EVT);
-
+ iwl_rfkill_unregister(priv);
iwl4965_dealloc_ucode_pci(priv);
if (priv->rxq.bd)
iwl_rx_queue_free(priv, &priv->rxq);
iwl_hw_txq_ctx_free(priv);
- iwlcore_clear_stations_table(priv);
+ iwl_clear_stations_table(priv);
iwl_eeprom_free(priv);
{IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
#ifdef CONFIG_IWL5000
- {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
+ {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)},
+ {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)},
+ {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)},
+ {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)},
+ {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)},
+ {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)},
{IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)},
+ {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
+ {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)},
+ {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)},
{IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)},
#endif /* CONFIG_IWL5000 */
{0}