]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-4965-rs.c
iwlwifi: fix various spelling and typos
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / iwlwifi / iwl-4965-rs.c
index 7b74481f52827e940f11e2c3539155071656387f..2227ee4ad1affbb4ff72ce870d7012bee18791d0 100644 (file)
@@ -36,8 +36,7 @@
 
 #include <linux/workqueue.h>
 
-#include <net/mac80211.h>
-#include <linux/wireless.h>
+#define IWL 4965
 
 #include "../net/mac80211/ieee80211_rate.h"
 
@@ -113,24 +112,38 @@ struct iwl_rate_scale_priv {
        u8 is_dup;
        u8 phymode;
        u8 ibss_sta_added;
+       u32 supp_rates;
        u16 active_rate;
        u16 active_siso_rate;
        u16 active_mimo_rate;
        u16 active_rate_basic;
        struct iwl_link_quality_cmd lq;
        struct iwl_scale_tbl_info lq_info[LQ_SIZE];
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct dentry *rs_sta_dbgfs_scale_table_file;
+       struct dentry *rs_sta_dbgfs_stats_table_file;
+       struct iwl_rate dbg_fixed;
+       struct iwl_priv *drv;
+#endif
 };
 
 static void rs_rate_scale_perform(struct iwl_priv *priv,
                                   struct net_device *dev,
                                   struct ieee80211_hdr *hdr,
                                   struct sta_info *sta);
-static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
+static void rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
                             struct iwl_rate *tx_mcs,
-                            struct iwl_link_quality_cmd *tbl,
-                            struct sta_info *sta);
+                            struct iwl_link_quality_cmd *tbl);
 
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+static void rs_dbgfs_set_mcs(struct iwl_rate_scale_priv *rs_priv,
+                               struct iwl_rate *mcs, int index);
+#else
+static void rs_dbgfs_set_mcs(struct iwl_rate_scale_priv *rs_priv,
+                               struct iwl_rate *mcs, int index)
+{}
+#endif
 static s32 expected_tpt_A[IWL_RATE_COUNT] = {
        0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186
 };
@@ -485,7 +498,7 @@ static u16 rs_get_adjacent_rate(u8 index, u16 rate_mask, int rate_type)
        u8 high = IWL_RATE_INVALID;
        u8 low = IWL_RATE_INVALID;
 
-       /* 802.11A or ht walks to the next literal adjascent rate in
+       /* 802.11A or ht walks to the next literal adjacent rate in
         * the rate table */
        if (is_a_band(rate_type) || !is_legacy(rate_type)) {
                int i;
@@ -537,14 +550,13 @@ static u16 rs_get_adjacent_rate(u8 index, u16 rate_mask, int rate_type)
 
 static int rs_get_lower_rate(struct iwl_rate_scale_priv *lq_data,
                             struct iwl_scale_tbl_info *tbl, u8 scale_index,
-                            u8 ht_possible, struct iwl_rate *mcs_rate,
-                            struct sta_info *sta)
+                            u8 ht_possible, struct iwl_rate *mcs_rate)
 {
-       u8 is_green = lq_data->is_green;
        s32 low;
        u16 rate_mask;
        u16 high_low;
        u8 switch_to_legacy = 0;
+       u8 is_green = lq_data->is_green;
 
        /* check if we need to switch from HT to legacy rates.
         * assumption is that mandatory rates (1Mbps or 6Mbps)
@@ -571,9 +583,9 @@ static int rs_get_lower_rate(struct iwl_rate_scale_priv *lq_data,
        if (is_legacy(tbl->lq_type)) {
                if (lq_data->phymode == (u8) MODE_IEEE80211A)
                        rate_mask  = (u16)(rate_mask &
-                          (sta->supp_rates << IWL_FIRST_OFDM_RATE));
+                          (lq_data->supp_rates << IWL_FIRST_OFDM_RATE));
                else
-                       rate_mask = (u16)(rate_mask & sta->supp_rates);
+                       rate_mask = (u16)(rate_mask & lq_data->supp_rates);
        }
 
        /* if we did switched from HT to legacy check current rate */
@@ -617,7 +629,7 @@ static void rs_tx_status(void *priv_rate,
        u16 fc = le16_to_cpu(hdr->frame_control);
        s32 tpt = 0;
 
-       IWL_DEBUG_RATE("get frame ack response, update rate scale window\n");
+       IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n");
 
        if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
                return;
@@ -1386,10 +1398,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
        if (is_legacy(tbl->lq_type)) {
                if (lq_data->phymode == (u8) MODE_IEEE80211A)
                        rate_scale_index_msk = (u16) (rate_mask &
-                               (sta->supp_rates << IWL_FIRST_OFDM_RATE));
+                               (lq_data->supp_rates << IWL_FIRST_OFDM_RATE));
                else
                        rate_scale_index_msk = (u16) (rate_mask &
-                                                     sta->supp_rates);
+                                                     lq_data->supp_rates);
 
        } else
                rate_scale_index_msk = rate_mask;
@@ -1401,7 +1413,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
                index = IWL_INVALID_VALUE;
                update_lq = 1;
 
-               /* get the lowest availabe rate */
+               /* get the lowest available rate */
                for (i = 0; i <= IWL_RATE_COUNT; i++) {
                        if ((1 << i) & rate_scale_index_msk)
                                index = i;
@@ -1429,7 +1441,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
                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);
+                       rs_fill_link_cmd(lq_data, &mcs_rate, &lq_data->lq);
                        rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC);
                }
                goto out;
@@ -1553,7 +1565,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
  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);
+               rs_fill_link_cmd(lq_data, &mcs_rate, &lq_data->lq);
                rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC);
        }
        rs_stay_in_table(lq_data);
@@ -1579,7 +1591,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
                        IWL_DEBUG_HT("Switch current  mcs: %X index: %d\n",
                                     tbl->current_rate.rate_n_flags, index);
                        rs_fill_link_cmd(lq_data, &tbl->current_rate,
-                                        &(lq_data->lq), sta);
+                                        &lq_data->lq);
                        rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC);
                }
                tbl1 = &(lq_data->lq_info[lq_data->active_tbl]);
@@ -1670,66 +1682,38 @@ static void rs_initialize_lq(struct iwl_priv *priv,
        tbl->antenna_type = ANT_AUX;
        rs_get_tbl_info_from_mcs(&mcs_rate, priv->phymode, tbl, &rate_idx);
        if (!rs_is_ant_connected(priv->valid_antenna, tbl->antenna_type))
-           rs_toggle_antenna(&mcs_rate, tbl),
+           rs_toggle_antenna(&mcs_rate, tbl);
 
        rs_mcs_from_tbl(&mcs_rate, tbl, rate_idx, use_green);
        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);
+       rs_fill_link_cmd(lq, &mcs_rate, &lq->lq);
        rs_send_lq_cmd(priv, &lq->lq, CMD_ASYNC);
  out:
        return;
 }
 
-static struct ieee80211_rate *rs_get_lowest_rate(struct ieee80211_local
-                                                *local)
-{
-       struct ieee80211_hw_mode *mode = local->oper_hw_mode;
-       int i;
-
-       for (i = 0; i < mode->num_rates; i++) {
-               struct ieee80211_rate *rate = &mode->rates[i];
-
-               if (rate->flags & IEEE80211_RATE_SUPPORTED)
-                       return rate;
-       }
-
-       return &mode->rates[0];
-}
-
-static struct ieee80211_rate *rs_get_rate(void *priv_rate,
-                                              struct net_device *dev,
-                                              struct sk_buff *skb,
-                                              struct rate_control_extra
-                                              *extra)
+static void rs_get_rate(void *priv_rate, struct net_device *dev,
+                       struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+                       struct rate_selection *sel)
 {
 
        int i;
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct sta_info *sta;
-       u16 fc;
        struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
        struct iwl_rate_scale_priv *lq;
 
-       IWL_DEBUG_RATE("rate scale calculate new rate for skb\n");
-
-       memset(extra, 0, sizeof(*extra));
-
-       fc = le16_to_cpu(hdr->frame_control);
-       if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) {
-               /* Send management frames and broadcast/multicast data using
-                * lowest rate. */
-               /* TODO: this could probably be improved.. */
-               return rs_get_lowest_rate(local);
-       }
+       IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
 
        sta = sta_info_get(local, hdr->addr1);
 
        if (!sta || !sta->rate_ctrl_priv) {
+               sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
                if (sta)
                        sta_info_put(sta);
-               return rs_get_lowest_rate(local);
+               return;
        }
 
        lq = (struct iwl_rate_scale_priv *)sta->rate_ctrl_priv;
@@ -1756,11 +1740,13 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate,
        }
 
  done:
+       if ((i < 0) || (i > IWL_RATE_COUNT)) {
+               sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+               return;
+       }
        sta_info_put(sta);
-       if ((i < 0) || (i > IWL_RATE_COUNT))
-               return rs_get_lowest_rate(local);
 
-       return &priv->ieee_rates[i];
+       sel->rate = &priv->ieee_rates[i];
 }
 
 static void *rs_alloc_sta(void *priv, gfp_t gfp)
@@ -1774,10 +1760,9 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp)
 
        if (crl == NULL)
                return NULL;
-
-       memset(crl, 0, sizeof(struct iwl_rate_scale_priv));
        crl->lq.sta_id = 0xff;
 
+
        for (j = 0; j < LQ_SIZE; j++)
                for (i = 0; i < IWL_RATE_COUNT; i++)
                        rs_rate_scale_clear_window(&(crl->lq_info[j].win[i]));
@@ -1794,10 +1779,8 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
        struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
        struct iwl_rate_scale_priv *crl = priv_sta;
 
-       memset(crl, 0, sizeof(struct iwl_rate_scale_priv));
-
-       crl->lq.sta_id = 0xff;
        crl->flush_timer = 0;
+       crl->supp_rates = sta->supp_rates;
        sta->txrate = 3;
        for (j = 0; j < LQ_SIZE; j++)
                for (i = 0; i < IWL_RATE_COUNT; i++)
@@ -1865,6 +1848,9 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
        IWL_DEBUG_HT("MIMO RATE 0x%X SISO MASK 0x%X\n", crl->active_siso_rate,
                     crl->active_mimo_rate);
 #endif /*CONFIG_IWLWIFI_HT*/
+#ifdef CONFIG_MAC80211_DEBUGFS
+       crl->drv = priv;
+#endif
 
        if (priv->assoc_station_added)
                priv->lq_mngr.lq_ready = 1;
@@ -1872,28 +1858,28 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
        rs_initialize_lq(priv, sta);
 }
 
-static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
+static void rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
                            struct iwl_rate *tx_mcs,
-                           struct iwl_link_quality_cmd *lq_cmd,
-                           struct sta_info *sta)
+                           struct iwl_link_quality_cmd *lq_cmd)
 {
        int index = 0;
-       int rc = 0;
        int rate_idx;
+       int repeat_rate = 0;
        u8 ant_toggle_count = 0;
        u8 use_ht_possible = 1;
-       u8 repeat_cur_rate = 0;
        struct iwl_rate new_rate;
        struct iwl_scale_tbl_info tbl_type = { 0 };
 
+       rs_dbgfs_set_mcs(lq_data, tx_mcs, index);
+
        rs_get_tbl_info_from_mcs(tx_mcs, lq_data->phymode,
                                  &tbl_type, &rate_idx);
 
        if (is_legacy(tbl_type.lq_type)) {
                ant_toggle_count = 1;
-               repeat_cur_rate = IWL_NUMBER_TRY;
+               repeat_rate = IWL_NUMBER_TRY;
        } else
-               repeat_cur_rate = IWL_HT_NUMBER_TRY;
+               repeat_rate = IWL_HT_NUMBER_TRY;
 
        lq_cmd->general_params.mimo_delimiter =
                        is_mimo(tbl_type.lq_type) ? 1 : 0;
@@ -1907,10 +1893,10 @@ static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
                lq_cmd->general_params.single_stream_ant_msk = 2;
 
        index++;
-       repeat_cur_rate--;
+       repeat_rate--;
 
        while (index < LINK_QUAL_MAX_RETRY_NUM) {
-               while (repeat_cur_rate && (index < LINK_QUAL_MAX_RETRY_NUM)) {
+               while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
                        if (is_legacy(tbl_type.lq_type)) {
                                if (ant_toggle_count <
                                    NUM_TRY_BEFORE_ANTENNA_TOGGLE)
@@ -1920,9 +1906,11 @@ static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
                                        ant_toggle_count = 1;
                                }
                        }
+
+                       rs_dbgfs_set_mcs(lq_data, &new_rate, index);
                        lq_cmd->rs_table[index].rate_n_flags =
                                        cpu_to_le32(new_rate.rate_n_flags);
-                       repeat_cur_rate--;
+                       repeat_rate--;
                        index++;
                }
 
@@ -1933,7 +1921,7 @@ static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
                        lq_cmd->general_params.mimo_delimiter = index;
 
                rs_get_lower_rate(lq_data, &tbl_type, rate_idx,
-                                 use_ht_possible, &new_rate, sta);
+                                 use_ht_possible, &new_rate);
 
                if (is_legacy(tbl_type.lq_type)) {
                        if (ant_toggle_count < NUM_TRY_BEFORE_ANTENNA_TOGGLE)
@@ -1942,26 +1930,23 @@ static int rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
                                rs_toggle_antenna(&new_rate, &tbl_type);
                                ant_toggle_count = 1;
                        }
-                       repeat_cur_rate = IWL_NUMBER_TRY;
+                       repeat_rate = IWL_NUMBER_TRY;
                } else
-                       repeat_cur_rate = IWL_HT_NUMBER_TRY;
+                       repeat_rate = IWL_HT_NUMBER_TRY;
 
                use_ht_possible = 0;
 
+               rs_dbgfs_set_mcs(lq_data, &new_rate, index);
                lq_cmd->rs_table[index].rate_n_flags =
                                cpu_to_le32(new_rate.rate_n_flags);
-               /* lq_cmd->rs_table[index].rate_n_flags = 0x800d; */
 
                index++;
-               repeat_cur_rate--;
+               repeat_rate--;
        }
 
-       /* lq_cmd->rs_table[0].rate_n_flags = 0x800d; */
-
        lq_cmd->general_params.dual_stream_ant_msk = 3;
        lq_cmd->agg_params.agg_dis_start_th = 3;
        lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000);
-       return rc;
 }
 
 static void *rs_alloc(struct ieee80211_local *local)
@@ -2001,6 +1986,168 @@ static void rs_free_sta(void *priv, void *priv_sta)
 }
 
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+static void rs_dbgfs_set_mcs(struct iwl_rate_scale_priv *rs_priv,
+                               struct iwl_rate *mcs, int index)
+{
+       u32 base_rate;
+
+       if (rs_priv->phymode == (u8) MODE_IEEE80211A)
+               base_rate = 0x800D;
+       else
+               base_rate = 0x820A;
+
+       if (rs_priv->dbg_fixed.rate_n_flags) {
+               if (index < 12)
+                       mcs->rate_n_flags = rs_priv->dbg_fixed.rate_n_flags;
+               else
+                       mcs->rate_n_flags = base_rate;
+               IWL_DEBUG_RATE("Fixed rate ON\n");
+               return;
+       }
+
+       IWL_DEBUG_RATE("Fixed rate OFF\n");
+}
+
+static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
+                       const char __user *user_buf, size_t count, loff_t *ppos)
+{
+       struct iwl_rate_scale_priv *rs_priv = file->private_data;
+       char buf[64];
+       int buf_size;
+       u32 parsed_rate;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) -  1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+
+       if (sscanf(buf, "%x", &parsed_rate) == 1)
+               rs_priv->dbg_fixed.rate_n_flags = parsed_rate;
+       else
+               rs_priv->dbg_fixed.rate_n_flags = 0;
+
+       rs_priv->active_rate = 0x0FFF;
+       rs_priv->active_siso_rate = 0x1FD0;
+       rs_priv->active_mimo_rate = 0x1FD0;
+
+       IWL_DEBUG_RATE("sta_id %d rate 0x%X\n",
+               rs_priv->lq.sta_id, rs_priv->dbg_fixed.rate_n_flags);
+
+       if (rs_priv->dbg_fixed.rate_n_flags) {
+               rs_fill_link_cmd(rs_priv, &rs_priv->dbg_fixed, &rs_priv->lq);
+               rs_send_lq_cmd(rs_priv->drv, &rs_priv->lq, CMD_ASYNC);
+       }
+
+       return count;
+}
+
+static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
+                       char __user *user_buf, size_t count, loff_t *ppos)
+{
+       char buff[1024];
+       int desc = 0;
+       int i = 0;
+
+       struct iwl_rate_scale_priv *rs_priv = file->private_data;
+
+       desc += sprintf(buff+desc, "sta_id %d\n", rs_priv->lq.sta_id);
+       desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n",
+                       rs_priv->total_failed, rs_priv->total_success,
+                       rs_priv->active_rate);
+       desc += sprintf(buff+desc, "fixed rate 0x%X\n",
+                       rs_priv->dbg_fixed.rate_n_flags);
+       desc += sprintf(buff+desc, "general:"
+               "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n",
+               rs_priv->lq.general_params.flags,
+               rs_priv->lq.general_params.mimo_delimiter,
+               rs_priv->lq.general_params.single_stream_ant_msk,
+               rs_priv->lq.general_params.dual_stream_ant_msk);
+
+       desc += sprintf(buff+desc, "agg:"
+                       "time_limit=%d dist_start_th=%d frame_cnt_limit=%d\n",
+                       le16_to_cpu(rs_priv->lq.agg_params.agg_time_limit),
+                       rs_priv->lq.agg_params.agg_dis_start_th,
+                       rs_priv->lq.agg_params.agg_frame_cnt_limit);
+
+       desc += sprintf(buff+desc,
+                       "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n",
+                       rs_priv->lq.general_params.start_rate_index[0],
+                       rs_priv->lq.general_params.start_rate_index[1],
+                       rs_priv->lq.general_params.start_rate_index[2],
+                       rs_priv->lq.general_params.start_rate_index[3]);
+
+
+       for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+               desc += sprintf(buff+desc, " rate[%d] 0x%X\n",
+                       i, le32_to_cpu(rs_priv->lq.rs_table[i].rate_n_flags));
+
+       return simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+}
+
+static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
+       .write = rs_sta_dbgfs_scale_table_write,
+       .read = rs_sta_dbgfs_scale_table_read,
+       .open = open_file_generic,
+};
+static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
+                       char __user *user_buf, size_t count, loff_t *ppos)
+{
+       char buff[1024];
+       int desc = 0;
+       int i, j;
+
+       struct iwl_rate_scale_priv *rs_priv = file->private_data;
+       for (i = 0; i < LQ_SIZE; i++) {
+               desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n"
+                               "rate=0x%X\n",
+                               rs_priv->active_tbl == i?"*":"x",
+                               rs_priv->lq_info[i].lq_type,
+                               rs_priv->lq_info[i].is_SGI,
+                               rs_priv->lq_info[i].is_fat,
+                               rs_priv->lq_info[i].is_dup,
+                               rs_priv->lq_info[i].current_rate.rate_n_flags);
+               for (j = 0; j < IWL_RATE_COUNT; j++) {
+                       desc += sprintf(buff+desc,
+                                       "counter=%d success=%d %%=%d\n",
+                                       rs_priv->lq_info[i].win[j].counter,
+                                       rs_priv->lq_info[i].win[j].success_counter,
+                                       rs_priv->lq_info[i].win[j].success_ratio);
+               }
+       }
+       return simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+}
+
+static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
+       .read = rs_sta_dbgfs_stats_table_read,
+       .open = open_file_generic,
+};
+
+static void rs_add_debugfs(void *priv, void *priv_sta,
+                                       struct dentry *dir)
+{
+       struct iwl_rate_scale_priv *rs_priv = priv_sta;
+       rs_priv->rs_sta_dbgfs_scale_table_file =
+               debugfs_create_file("rate_scale_table", 0600, dir,
+                               rs_priv, &rs_sta_dbgfs_scale_table_ops);
+       rs_priv->rs_sta_dbgfs_stats_table_file =
+               debugfs_create_file("rate_stats_table", 0600, dir,
+                       rs_priv, &rs_sta_dbgfs_stats_table_ops);
+}
+
+static void rs_remove_debugfs(void *priv, void *priv_sta)
+{
+       struct iwl_rate_scale_priv *rs_priv = priv_sta;
+       debugfs_remove(rs_priv->rs_sta_dbgfs_scale_table_file);
+       debugfs_remove(rs_priv->rs_sta_dbgfs_stats_table_file);
+}
+#endif
+
 static struct rate_control_ops rs_ops = {
        .module = NULL,
        .name = RS_NAME,
@@ -2012,6 +2159,10 @@ static struct rate_control_ops rs_ops = {
        .free = rs_free,
        .alloc_sta = rs_alloc_sta,
        .free_sta = rs_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+       .add_sta_debugfs = rs_add_debugfs,
+       .remove_sta_debugfs = rs_remove_debugfs,
+#endif
 };
 
 int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
@@ -2094,7 +2245,7 @@ int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
                         max_time, good * 100 / samples, good, samples);
        else
                count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n");
-       count += sprintf(&buf[count], "\nrate scale type %d anntena %d "
+       count += sprintf(&buf[count], "\nrate scale type %d antenna %d "
                         "active_search %d rate index %d\n", lq_type, antenna,
                         rs_priv->search_better_tbl, sta->last_txrate);