aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c216
1 files changed, 211 insertions, 5 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 9ca539861db2..da51349cbd8b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -29,17 +29,223 @@
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/version.h> 31#include <linux/version.h>
32#include <net/mac80211.h>
32 33
33#include "iwl-4965-debug.h" 34struct iwl_priv; /* FIXME: remove */
35#include "iwl-debug.h"
34#include "iwl-eeprom.h" 36#include "iwl-eeprom.h"
35#include "iwl-core.h" 37#include "iwl-core.h"
36 38
39#include "iwl-4965.h" /* FIXME: remove */
40
37MODULE_DESCRIPTION("iwl core"); 41MODULE_DESCRIPTION("iwl core");
38MODULE_VERSION(IWLWIFI_VERSION); 42MODULE_VERSION(IWLWIFI_VERSION);
39MODULE_AUTHOR(DRV_COPYRIGHT); 43MODULE_AUTHOR(DRV_COPYRIGHT);
40MODULE_LICENSE("GPL/BSD"); 44MODULE_LICENSE("GPL");
41 45
42#ifdef CONFIG_IWL4965_DEBUG 46#ifdef CONFIG_IWLWIFI_DEBUG
43u32 iwl4965_debug_level; 47u32 iwl_debug_level;
44EXPORT_SYMBOL(iwl4965_debug_level); 48EXPORT_SYMBOL(iwl_debug_level);
45#endif 49#endif
50
51/* This function both allocates and initializes hw and priv. */
52struct 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
69out:
70 return hw;
71}
72EXPORT_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 */
79void 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}
90EXPORT_SYMBOL(iwlcore_clear_stations_table);
91
92void 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}
178EXPORT_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 */
190int 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}
216EXPORT_SYMBOL(iwlcore_set_rxon_channel);
217
218static 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
243int 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}
250EXPORT_SYMBOL(iwl_setup);
251