Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-core.c
1 /******************************************************************************
2  *
3  * GPL LICENSE SUMMARY
4  *
5  * Copyright(c) 2008 Intel Corporation. All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of version 2 of the GNU General Public License as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
19  * USA
20  *
21  * The full GNU General Public License is included in this distribution
22  * in the file called LICENSE.GPL.
23  *
24  * Contact Information:
25  * Tomas Winkler <tomas.winkler@intel.com>
26  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27  *****************************************************************************/
28
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/version.h>
32 #include <net/mac80211.h>
33
34 struct iwl_priv; /* FIXME: remove */
35 #include "iwl-debug.h"
36 #include "iwl-eeprom.h"
37 #include "iwl-core.h"
38
39 #include "iwl-4965.h" /* FIXME: remove */
40
41 MODULE_DESCRIPTION("iwl core");
42 MODULE_VERSION(IWLWIFI_VERSION);
43 MODULE_AUTHOR(DRV_COPYRIGHT);
44 MODULE_LICENSE("GPL");
45
46 #ifdef CONFIG_IWLWIFI_DEBUG
47 u32 iwl_debug_level;
48 EXPORT_SYMBOL(iwl_debug_level);
49 #endif
50
51 /* This function both allocates and initializes hw and priv. */
52 struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
53                 struct ieee80211_ops *hw_ops)
54 {
55         struct iwl_priv *priv;
56
57         /* mac80211 allocates memory for this device instance, including
58          *   space for this driver's private structure */
59         struct ieee80211_hw *hw =
60                 ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops);
61         if (hw == NULL) {
62                 IWL_ERROR("Can not allocate network device\n");
63                 goto out;
64         }
65
66         priv = hw->priv;
67         priv->hw = hw;
68
69 out:
70         return hw;
71 }
72 EXPORT_SYMBOL(iwl_alloc_all);
73
74 /**
75  * iwlcore_clear_stations_table - Clear the driver's station table
76  *
77  * NOTE:  This does not clear or otherwise alter the device's station table.
78  */
79 void iwlcore_clear_stations_table(struct iwl_priv *priv)
80 {
81         unsigned long flags;
82
83         spin_lock_irqsave(&priv->sta_lock, flags);
84
85         priv->num_stations = 0;
86         memset(priv->stations, 0, sizeof(priv->stations));
87
88         spin_unlock_irqrestore(&priv->sta_lock, flags);
89 }
90 EXPORT_SYMBOL(iwlcore_clear_stations_table);
91
92 void iwlcore_reset_qos(struct iwl_priv *priv)
93 {
94         u16 cw_min = 15;
95         u16 cw_max = 1023;
96         u8 aifs = 2;
97         u8 is_legacy = 0;
98         unsigned long flags;
99         int i;
100
101         spin_lock_irqsave(&priv->lock, flags);
102         priv->qos_data.qos_active = 0;
103
104         if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
105                 if (priv->qos_data.qos_enable)
106                         priv->qos_data.qos_active = 1;
107                 if (!(priv->active_rate & 0xfff0)) {
108                         cw_min = 31;
109                         is_legacy = 1;
110                 }
111         } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
112                 if (priv->qos_data.qos_enable)
113                         priv->qos_data.qos_active = 1;
114         } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
115                 cw_min = 31;
116                 is_legacy = 1;
117         }
118
119         if (priv->qos_data.qos_active)
120                 aifs = 3;
121
122         priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
123         priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
124         priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
125         priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
126         priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
127
128         if (priv->qos_data.qos_active) {
129                 i = 1;
130                 priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
131                 priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
132                 priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
133                 priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
134                 priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
135
136                 i = 2;
137                 priv->qos_data.def_qos_parm.ac[i].cw_min =
138                         cpu_to_le16((cw_min + 1) / 2 - 1);
139                 priv->qos_data.def_qos_parm.ac[i].cw_max =
140                         cpu_to_le16(cw_max);
141                 priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
142                 if (is_legacy)
143                         priv->qos_data.def_qos_parm.ac[i].edca_txop =
144                                 cpu_to_le16(6016);
145                 else
146                         priv->qos_data.def_qos_parm.ac[i].edca_txop =
147                                 cpu_to_le16(3008);
148                 priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
149
150                 i = 3;
151                 priv->qos_data.def_qos_parm.ac[i].cw_min =
152                         cpu_to_le16((cw_min + 1) / 4 - 1);
153                 priv->qos_data.def_qos_parm.ac[i].cw_max =
154                         cpu_to_le16((cw_max + 1) / 2 - 1);
155                 priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
156                 priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
157                 if (is_legacy)
158                         priv->qos_data.def_qos_parm.ac[i].edca_txop =
159                                 cpu_to_le16(3264);
160                 else
161                         priv->qos_data.def_qos_parm.ac[i].edca_txop =
162                                 cpu_to_le16(1504);
163         } else {
164                 for (i = 1; i < 4; i++) {
165                         priv->qos_data.def_qos_parm.ac[i].cw_min =
166                                 cpu_to_le16(cw_min);
167                         priv->qos_data.def_qos_parm.ac[i].cw_max =
168                                 cpu_to_le16(cw_max);
169                         priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
170                         priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
171                         priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
172                 }
173         }
174         IWL_DEBUG_QOS("set QoS to default \n");
175
176         spin_unlock_irqrestore(&priv->lock, flags);
177 }
178 EXPORT_SYMBOL(iwlcore_reset_qos);
179
180 /**
181  * iwlcore_set_rxon_channel - Set the phymode and channel values in staging RXON
182  * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
183  * @channel: Any channel valid for the requested phymode
184
185  * In addition to setting the staging RXON, priv->phymode is also set.
186  *
187  * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
188  * in the staging RXON flag structure based on the phymode
189  */
190 int iwlcore_set_rxon_channel(struct iwl_priv *priv,
191                                 enum ieee80211_band band,
192                                 u16 channel)
193 {
194         if (!iwl_get_channel_info(priv, band, channel)) {
195                 IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
196                                channel, band);
197                 return -EINVAL;
198         }
199
200         if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
201             (priv->band == band))
202                 return 0;
203
204         priv->staging_rxon.channel = cpu_to_le16(channel);
205         if (band == IEEE80211_BAND_5GHZ)
206                 priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
207         else
208                 priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
209
210         priv->band = band;
211
212         IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
213
214         return 0;
215 }
216 EXPORT_SYMBOL(iwlcore_set_rxon_channel);
217
218 static void iwlcore_init_hw(struct iwl_priv *priv)
219 {
220         struct ieee80211_hw *hw = priv->hw;
221         hw->rate_control_algorithm = "iwl-4965-rs";
222
223         /* Tell mac80211 and its clients (e.g. Wireless Extensions)
224          *       the range of signal quality values that we'll provide.
225          * Negative values for level/noise indicate that we'll provide dBm.
226          * For WE, at least, non-0 values here *enable* display of values
227          *       in app (iwconfig). */
228         hw->max_rssi = -20; /* signal level, negative indicates dBm */
229         hw->max_noise = -20;    /* noise level, negative indicates dBm */
230         hw->max_signal = 100;   /* link quality indication (%) */
231
232         /* Tell mac80211 our Tx characteristics */
233         hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
234
235         /* Default value; 4 EDCA QOS priorities */
236         hw->queues = 4;
237 #ifdef CONFIG_IWL4965_HT
238         /* Enhanced value; more queues, to support 11n aggregation */
239         hw->queues = 16;
240 #endif /* CONFIG_IWL4965_HT */
241 }
242
243 int iwl_setup(struct iwl_priv *priv)
244 {
245         int ret = 0;
246         iwlcore_init_hw(priv);
247         ret = priv->cfg->ops->lib->init_drv(priv);
248         return ret;
249 }
250 EXPORT_SYMBOL(iwl_setup);
251