iwlwifi: move beacon handling to iwl4965-base.c
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / iwl4965-base.c
index d6fe0ded59d70089cd864846bbb7e84b69540ee6..94ce026ba6026a0d681916ee03b69ca86360ec61 100644 (file)
@@ -65,7 +65,7 @@
  * 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"
@@ -250,6 +250,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
 
        /* always get timestamp with Rx frame */
        priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
+       /* allow CTS-to-self if possible. this is relevant only for
+        * 5000, but will not damage 4965 */
+       priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
 
        ret = iwl4965_check_rxon_cmd(&priv->staging_rxon);
        if (ret) {
@@ -325,16 +328,6 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
        if (!priv->error_recovering)
                priv->start_calib = 0;
 
-       iwl_init_sensitivity(priv);
-
-       /* If we issue a new RXON command which required a tune then we must
-        * send a new TXPOWER command or we won't be able to Tx any frames */
-       ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
-       if (ret) {
-               IWL_ERROR("Error sending TX power (%d)\n", ret);
-               return ret;
-       }
-
        /* Add the broadcast address so we can send broadcast frames */
        if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
                                                IWL_INVALID_STATION) {
@@ -370,6 +363,16 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
                memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
        }
 
+       iwl_init_sensitivity(priv);
+
+       /* If we issue a new RXON command which required a tune then we must
+        * send a new TXPOWER command or we won't be able to Tx any frames */
+       ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+       if (ret) {
+               IWL_ERROR("Error sending TX power (%d)\n", ret);
+               return ret;
+       }
+
        return 0;
 }
 
@@ -441,11 +444,10 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
        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)))
@@ -484,6 +486,38 @@ static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
                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;
@@ -572,25 +606,14 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
 /*
  * QoS  support
 */
-static int iwl4965_send_qos_params_command(struct iwl_priv *priv,
-                                      struct iwl4965_qosparam_cmd *qos)
-{
-
-       return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
-                               sizeof(struct iwl4965_qosparam_cmd), qos);
-}
-
-static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
+static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
 {
-       unsigned long flags;
-
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
        if (!priv->qos_data.qos_enable)
                return;
 
-       spin_lock_irqsave(&priv->lock, flags);
        priv->qos_data.def_qos_parm.qos_flags = 0;
 
        if (priv->qos_data.qos_cap.q_AP.queue_request &&
@@ -604,15 +627,14 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
        if (priv->current_ht_config.is_ht)
                priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
 
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        if (force || iwl_is_associated(priv)) {
                IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
                                priv->qos_data.qos_active,
                                priv->qos_data.def_qos_parm.qos_flags);
 
-               iwl4965_send_qos_params_command(priv,
-                               &(priv->qos_data.def_qos_parm));
+               iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
+                                      sizeof(struct iwl_qosparam_cmd),
+                                      &priv->qos_data.def_qos_parm, NULL);
        }
 }
 
@@ -2421,6 +2443,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
        struct ieee80211_conf *conf = NULL;
        int ret = 0;
        DECLARE_MAC_BUF(mac);
+       unsigned long flags;
 
        if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
                IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__);
@@ -2510,25 +2533,15 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
        if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
                priv->assoc_station_added = 1;
 
-       iwl4965_activate_qos(priv, 0);
+       spin_lock_irqsave(&priv->lock, flags);
+       iwl_activate_qos(priv, 0);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        iwl_power_update_mode(priv, 0);
        /* we have just associated, don't start scan too early */
        priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
 }
 
-
-static void iwl4965_bg_post_associate(struct work_struct *data)
-{
-       struct iwl_priv *priv = container_of(data, struct iwl_priv,
-                                            post_associate.work);
-
-       mutex_lock(&priv->mutex);
-       iwl4965_post_associate(priv);
-       mutex_unlock(&priv->mutex);
-
-}
-
 static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
 
 static void iwl_bg_scan_completed(struct work_struct *work)
@@ -2659,7 +2672,6 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
                 */
                mutex_lock(&priv->mutex);
                iwl_scan_cancel_timeout(priv, 100);
-               cancel_delayed_work(&priv->post_associate);
                mutex_unlock(&priv->mutex);
        }
 
@@ -2855,6 +2867,7 @@ out:
 static void iwl4965_config_ap(struct iwl_priv *priv)
 {
        int ret = 0;
+       unsigned long flags;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -2902,7 +2915,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
                /* restore RXON assoc */
                priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
                iwl4965_commit_rxon(priv);
-               iwl4965_activate_qos(priv, 1);
+               spin_lock_irqsave(&priv->lock, flags);
+               iwl_activate_qos(priv, 1);
+               spin_unlock_irqrestore(&priv->lock, flags);
                iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
        }
        iwl4965_send_beacon_cmd(priv);
@@ -3061,7 +3076,6 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
 
        if (iwl_is_ready_rf(priv)) {
                iwl_scan_cancel_timeout(priv, 100);
-               cancel_delayed_work(&priv->post_associate);
                priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
                iwl4965_commit_rxon(priv);
        }
@@ -3351,20 +3365,50 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
        priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
        priv->qos_data.qos_active = 1;
 
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       mutex_lock(&priv->mutex);
        if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
-               iwl4965_activate_qos(priv, 1);
+               iwl_activate_qos(priv, 1);
        else if (priv->assoc_id && iwl_is_associated(priv))
-               iwl4965_activate_qos(priv, 0);
+               iwl_activate_qos(priv, 0);
 
-       mutex_unlock(&priv->mutex);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        IWL_DEBUG_MAC80211("leave\n");
        return 0;
 }
 
+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)
 {
@@ -3426,8 +3470,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
 
        iwl_reset_qos(priv);
 
-       cancel_delayed_work(&priv->post_associate);
-
        spin_lock_irqsave(&priv->lock, flags);
        priv->assoc_id = 0;
        priv->assoc_capability = 0;
@@ -3822,76 +3864,53 @@ static ssize_t store_power_level(struct device *d,
                                 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);
 }
 
@@ -4029,7 +4048,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
        INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
        INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
        INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
-       INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate);
        INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
        INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
 
@@ -4056,7 +4074,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
        cancel_delayed_work_sync(&priv->init_alive_start);
        cancel_delayed_work(&priv->scan_check);
        cancel_delayed_work(&priv->alive_start);
-       cancel_delayed_work(&priv->post_associate);
        cancel_work_sync(&priv->beacon_update);
        del_timer_sync(&priv->statistics_periodic);
 }
@@ -4421,8 +4438,16 @@ static struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
        {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
 #ifdef CONFIG_IWL5000
-       {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)},
+       {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)},
        {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)},
+       {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
+       {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)},
+       {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)},
        {IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)},
 #endif /* CONFIG_IWL5000 */
        {0}
This page took 0.030294 seconds and 5 git commands to generate.