* NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
*/
-#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link 4965AGN driver for Linux"
+#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux"
#ifdef CONFIG_IWLWIFI_DEBUG
#define VD "d"
/* always get timestamp with Rx frame */
priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
+ /* allow CTS-to-self if possible. this is relevant only for
+ * 5000, but will not damage 4965 */
+ priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
ret = iwl4965_check_rxon_cmd(&priv->staging_rxon);
if (ret) {
if (!priv->error_recovering)
priv->start_calib = 0;
- iwl_init_sensitivity(priv);
-
- /* If we issue a new RXON command which required a tune then we must
- * send a new TXPOWER command or we won't be able to Tx any frames */
- ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
- if (ret) {
- IWL_ERROR("Error sending TX power (%d)\n", ret);
- return ret;
- }
-
/* Add the broadcast address so we can send broadcast frames */
if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
IWL_INVALID_STATION) {
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
}
+ iwl_init_sensitivity(priv);
+
+ /* If we issue a new RXON command which required a tune then we must
+ * send a new TXPOWER command or we won't be able to Tx any frames */
+ ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+ if (ret) {
+ IWL_ERROR("Error sending TX power (%d)\n", ret);
+ return ret;
+ }
+
return 0;
}
list_add(&frame->list, &priv->free_frames);
}
-unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr,
- const u8 *dest, int left)
+static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
+ struct ieee80211_hdr *hdr,
+ const u8 *dest, int left)
{
-
if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
(priv->iw_mode != IEEE80211_IF_TYPE_AP)))
return IWL_RATE_6M_PLCP;
}
+unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+ struct iwl_frame *frame, u8 rate)
+{
+ struct iwl_tx_beacon_cmd *tx_beacon_cmd;
+ unsigned int frame_size;
+
+ tx_beacon_cmd = &frame->u.beacon;
+ memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+
+ tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
+ tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+ frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame,
+ iwl_bcast_addr,
+ sizeof(frame->u) - sizeof(*tx_beacon_cmd));
+
+ BUG_ON(frame_size > MAX_MPDU_SIZE);
+ tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
+
+ if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP))
+ tx_beacon_cmd->tx.rate_n_flags =
+ iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK);
+ else
+ tx_beacon_cmd->tx.rate_n_flags =
+ iwl_hw_set_rate_n_flags(rate, 0);
+
+ tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
+ TX_CMD_FLG_TSF_MSK |
+ TX_CMD_FLG_STA_RATE_MSK;
+
+ return sizeof(*tx_beacon_cmd) + frame_size;
+}
static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
{
struct iwl_frame *frame;
/*
* QoS support
*/
-static int iwl4965_send_qos_params_command(struct iwl_priv *priv,
- struct iwl4965_qosparam_cmd *qos)
-{
-
- return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
- sizeof(struct iwl4965_qosparam_cmd), qos);
-}
-
-static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
+static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
{
- unsigned long flags;
-
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (!priv->qos_data.qos_enable)
return;
- spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.def_qos_parm.qos_flags = 0;
if (priv->qos_data.qos_cap.q_AP.queue_request &&
if (priv->current_ht_config.is_ht)
priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
- spin_unlock_irqrestore(&priv->lock, flags);
-
if (force || iwl_is_associated(priv)) {
IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
priv->qos_data.qos_active,
priv->qos_data.def_qos_parm.qos_flags);
- iwl4965_send_qos_params_command(priv,
- &(priv->qos_data.def_qos_parm));
+ iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
+ sizeof(struct iwl_qosparam_cmd),
+ &priv->qos_data.def_qos_parm, NULL);
}
}
struct ieee80211_conf *conf = NULL;
int ret = 0;
DECLARE_MAC_BUF(mac);
+ unsigned long flags;
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__);
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
priv->assoc_station_added = 1;
- iwl4965_activate_qos(priv, 0);
+ spin_lock_irqsave(&priv->lock, flags);
+ iwl_activate_qos(priv, 0);
+ spin_unlock_irqrestore(&priv->lock, flags);
iwl_power_update_mode(priv, 0);
/* we have just associated, don't start scan too early */
priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
}
-
-static void iwl4965_bg_post_associate(struct work_struct *data)
-{
- struct iwl_priv *priv = container_of(data, struct iwl_priv,
- post_associate.work);
-
- mutex_lock(&priv->mutex);
- iwl4965_post_associate(priv);
- mutex_unlock(&priv->mutex);
-
-}
-
static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
static void iwl_bg_scan_completed(struct work_struct *work)
*/
mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, 100);
- cancel_delayed_work(&priv->post_associate);
mutex_unlock(&priv->mutex);
}
static void iwl4965_config_ap(struct iwl_priv *priv)
{
int ret = 0;
+ unsigned long flags;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
/* restore RXON assoc */
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
iwl4965_commit_rxon(priv);
- iwl4965_activate_qos(priv, 1);
+ spin_lock_irqsave(&priv->lock, flags);
+ iwl_activate_qos(priv, 1);
+ spin_unlock_irqrestore(&priv->lock, flags);
iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
}
iwl4965_send_beacon_cmd(priv);
if (iwl_is_ready_rf(priv)) {
iwl_scan_cancel_timeout(priv, 100);
- cancel_delayed_work(&priv->post_associate);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl4965_commit_rxon(priv);
}
priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
priv->qos_data.qos_active = 1;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- mutex_lock(&priv->mutex);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
- iwl4965_activate_qos(priv, 1);
+ iwl_activate_qos(priv, 1);
else if (priv->assoc_id && iwl_is_associated(priv))
- iwl4965_activate_qos(priv, 0);
+ iwl_activate_qos(priv, 0);
- mutex_unlock(&priv->mutex);
+ spin_unlock_irqrestore(&priv->lock, flags);
IWL_DEBUG_MAC80211("leave\n");
return 0;
}
+static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+ enum ieee80211_ampdu_mlme_action action,
+ const u8 *addr, u16 tid, u16 *ssn)
+{
+ struct iwl_priv *priv = hw->priv;
+ DECLARE_MAC_BUF(mac);
+
+ IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n",
+ print_mac(mac, addr), tid);
+
+ if (!(priv->cfg->sku & IWL_SKU_N))
+ return -EACCES;
+
+ switch (action) {
+ case IEEE80211_AMPDU_RX_START:
+ IWL_DEBUG_HT("start Rx\n");
+ return iwl_rx_agg_start(priv, addr, tid, *ssn);
+ case IEEE80211_AMPDU_RX_STOP:
+ IWL_DEBUG_HT("stop Rx\n");
+ return iwl_rx_agg_stop(priv, addr, tid);
+ case IEEE80211_AMPDU_TX_START:
+ IWL_DEBUG_HT("start Tx\n");
+ return iwl_tx_agg_start(priv, addr, tid, ssn);
+ case IEEE80211_AMPDU_TX_STOP:
+ IWL_DEBUG_HT("stop Tx\n");
+ return iwl_tx_agg_stop(priv, addr, tid);
+ default:
+ IWL_DEBUG_HT("unknown\n");
+ return -EINVAL;
+ break;
+ }
+ return 0;
+}
static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats)
{
iwl_reset_qos(priv);
- cancel_delayed_work(&priv->post_associate);
-
spin_lock_irqsave(&priv->lock, flags);
priv->assoc_id = 0;
priv->assoc_capability = 0;
const char *buf, size_t count)
{
struct iwl_priv *priv = dev_get_drvdata(d);
- int rc;
+ int ret;
int mode;
mode = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
if (!iwl_is_ready(priv)) {
- rc = -EAGAIN;
+ ret = -EAGAIN;
goto out;
}
- rc = iwl_power_set_user_mode(priv, mode);
- if (rc) {
+ ret = iwl_power_set_user_mode(priv, mode);
+ if (ret) {
IWL_DEBUG_MAC80211("failed setting power mode.\n");
goto out;
}
- rc = count;
+ ret = count;
out:
mutex_unlock(&priv->mutex);
- return rc;
+ return ret;
}
-#define MAX_WX_STRING 80
-
-/* Values are in microsecond */
-static const s32 timeout_duration[] = {
- 350000,
- 250000,
- 75000,
- 37000,
- 25000,
-};
-static const s32 period_duration[] = {
- 400000,
- 700000,
- 1000000,
- 1000000,
- 1000000
-};
-
static ssize_t show_power_level(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ int mode = priv->power_data.user_power_setting;
+ int system = priv->power_data.system_power_setting;
int level = priv->power_data.power_mode;
char *p = buf;
- p += sprintf(p, "%d ", level);
- switch (level) {
- case IWL_POWER_MODE_CAM:
- case IWL_POWER_AC:
- p += sprintf(p, "(AC)");
+ switch (system) {
+ case IWL_POWER_SYS_AUTO:
+ p += sprintf(p, "SYSTEM:auto");
break;
- case IWL_POWER_BATTERY:
- p += sprintf(p, "(BATTERY)");
+ case IWL_POWER_SYS_AC:
+ p += sprintf(p, "SYSTEM:ac");
+ break;
+ case IWL_POWER_SYS_BATTERY:
+ p += sprintf(p, "SYSTEM:battery");
break;
- default:
- p += sprintf(p,
- "(Timeout %dms, Period %dms)",
- timeout_duration[level - 1] / 1000,
- period_duration[level - 1] / 1000);
}
-/*
- if (!(priv->power_mode & IWL_POWER_ENABLED))
- p += sprintf(p, " OFF\n");
- else
- p += sprintf(p, " \n");
-*/
- p += sprintf(p, " \n");
+
+ p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO)?"fixed":"auto");
+ p += sprintf(p, "\tINDEX:%d", level);
+ p += sprintf(p, "\n");
return (p - buf + 1);
}
INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
- INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
- cancel_delayed_work(&priv->post_associate);
cancel_work_sync(&priv->beacon_update);
del_timer_sync(&priv->statistics_periodic);
}
{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}