1 /******************************************************************************
5 * Copyright(c) 2008 Intel Corporation. All rights reserved.
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.
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.
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,
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
24 * Contact Information:
25 * Tomas Winkler <tomas.winkler@intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *****************************************************************************/
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/version.h>
32 #include <net/mac80211.h>
34 struct iwl_priv
; /* FIXME: remove */
35 #include "iwl-debug.h"
36 #include "iwl-eeprom.h"
37 #include "iwl-4965.h" /* FIXME: remove */
40 #include "iwl-rfkill.h"
41 #include "iwl-power.h"
44 MODULE_DESCRIPTION("iwl core");
45 MODULE_VERSION(IWLWIFI_VERSION
);
46 MODULE_AUTHOR(DRV_COPYRIGHT
);
47 MODULE_LICENSE("GPL");
49 #ifdef CONFIG_IWLWIFI_DEBUG
51 EXPORT_SYMBOL(iwl_debug_level
);
54 /* This function both allocates and initializes hw and priv. */
55 struct ieee80211_hw
*iwl_alloc_all(struct iwl_cfg
*cfg
,
56 struct ieee80211_ops
*hw_ops
)
58 struct iwl_priv
*priv
;
60 /* mac80211 allocates memory for this device instance, including
61 * space for this driver's private structure */
62 struct ieee80211_hw
*hw
=
63 ieee80211_alloc_hw(sizeof(struct iwl_priv
), hw_ops
);
65 IWL_ERROR("Can not allocate network device\n");
75 EXPORT_SYMBOL(iwl_alloc_all
);
77 void iwl_hw_detect(struct iwl_priv
*priv
)
79 priv
->hw_rev
= _iwl_read32(priv
, CSR_HW_REV
);
80 priv
->hw_wa_rev
= _iwl_read32(priv
, CSR_HW_REV_WA_REG
);
81 pci_read_config_byte(priv
->pci_dev
, PCI_REVISION_ID
, &priv
->rev_id
);
83 EXPORT_SYMBOL(iwl_hw_detect
);
86 * iwlcore_clear_stations_table - Clear the driver's station table
88 * NOTE: This does not clear or otherwise alter the device's station table.
90 void iwlcore_clear_stations_table(struct iwl_priv
*priv
)
94 spin_lock_irqsave(&priv
->sta_lock
, flags
);
96 priv
->num_stations
= 0;
97 memset(priv
->stations
, 0, sizeof(priv
->stations
));
99 spin_unlock_irqrestore(&priv
->sta_lock
, flags
);
101 EXPORT_SYMBOL(iwlcore_clear_stations_table
);
103 void iwlcore_reset_qos(struct iwl_priv
*priv
)
112 spin_lock_irqsave(&priv
->lock
, flags
);
113 priv
->qos_data
.qos_active
= 0;
115 if (priv
->iw_mode
== IEEE80211_IF_TYPE_IBSS
) {
116 if (priv
->qos_data
.qos_enable
)
117 priv
->qos_data
.qos_active
= 1;
118 if (!(priv
->active_rate
& 0xfff0)) {
122 } else if (priv
->iw_mode
== IEEE80211_IF_TYPE_AP
) {
123 if (priv
->qos_data
.qos_enable
)
124 priv
->qos_data
.qos_active
= 1;
125 } else if (!(priv
->staging_rxon
.flags
& RXON_FLG_SHORT_SLOT_MSK
)) {
130 if (priv
->qos_data
.qos_active
)
133 priv
->qos_data
.def_qos_parm
.ac
[0].cw_min
= cpu_to_le16(cw_min
);
134 priv
->qos_data
.def_qos_parm
.ac
[0].cw_max
= cpu_to_le16(cw_max
);
135 priv
->qos_data
.def_qos_parm
.ac
[0].aifsn
= aifs
;
136 priv
->qos_data
.def_qos_parm
.ac
[0].edca_txop
= 0;
137 priv
->qos_data
.def_qos_parm
.ac
[0].reserved1
= 0;
139 if (priv
->qos_data
.qos_active
) {
141 priv
->qos_data
.def_qos_parm
.ac
[i
].cw_min
= cpu_to_le16(cw_min
);
142 priv
->qos_data
.def_qos_parm
.ac
[i
].cw_max
= cpu_to_le16(cw_max
);
143 priv
->qos_data
.def_qos_parm
.ac
[i
].aifsn
= 7;
144 priv
->qos_data
.def_qos_parm
.ac
[i
].edca_txop
= 0;
145 priv
->qos_data
.def_qos_parm
.ac
[i
].reserved1
= 0;
148 priv
->qos_data
.def_qos_parm
.ac
[i
].cw_min
=
149 cpu_to_le16((cw_min
+ 1) / 2 - 1);
150 priv
->qos_data
.def_qos_parm
.ac
[i
].cw_max
=
152 priv
->qos_data
.def_qos_parm
.ac
[i
].aifsn
= 2;
154 priv
->qos_data
.def_qos_parm
.ac
[i
].edca_txop
=
157 priv
->qos_data
.def_qos_parm
.ac
[i
].edca_txop
=
159 priv
->qos_data
.def_qos_parm
.ac
[i
].reserved1
= 0;
162 priv
->qos_data
.def_qos_parm
.ac
[i
].cw_min
=
163 cpu_to_le16((cw_min
+ 1) / 4 - 1);
164 priv
->qos_data
.def_qos_parm
.ac
[i
].cw_max
=
165 cpu_to_le16((cw_max
+ 1) / 2 - 1);
166 priv
->qos_data
.def_qos_parm
.ac
[i
].aifsn
= 2;
167 priv
->qos_data
.def_qos_parm
.ac
[i
].reserved1
= 0;
169 priv
->qos_data
.def_qos_parm
.ac
[i
].edca_txop
=
172 priv
->qos_data
.def_qos_parm
.ac
[i
].edca_txop
=
175 for (i
= 1; i
< 4; i
++) {
176 priv
->qos_data
.def_qos_parm
.ac
[i
].cw_min
=
178 priv
->qos_data
.def_qos_parm
.ac
[i
].cw_max
=
180 priv
->qos_data
.def_qos_parm
.ac
[i
].aifsn
= aifs
;
181 priv
->qos_data
.def_qos_parm
.ac
[i
].edca_txop
= 0;
182 priv
->qos_data
.def_qos_parm
.ac
[i
].reserved1
= 0;
185 IWL_DEBUG_QOS("set QoS to default \n");
187 spin_unlock_irqrestore(&priv
->lock
, flags
);
189 EXPORT_SYMBOL(iwlcore_reset_qos
);
192 * iwlcore_set_rxon_channel - Set the phymode and channel values in staging RXON
193 * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
194 * @channel: Any channel valid for the requested phymode
196 * In addition to setting the staging RXON, priv->phymode is also set.
198 * NOTE: Does not commit to the hardware; it sets appropriate bit fields
199 * in the staging RXON flag structure based on the phymode
201 int iwlcore_set_rxon_channel(struct iwl_priv
*priv
,
202 enum ieee80211_band band
,
205 if (!iwl_get_channel_info(priv
, band
, channel
)) {
206 IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
211 if ((le16_to_cpu(priv
->staging_rxon
.channel
) == channel
) &&
212 (priv
->band
== band
))
215 priv
->staging_rxon
.channel
= cpu_to_le16(channel
);
216 if (band
== IEEE80211_BAND_5GHZ
)
217 priv
->staging_rxon
.flags
&= ~RXON_FLG_BAND_24G_MSK
;
219 priv
->staging_rxon
.flags
|= RXON_FLG_BAND_24G_MSK
;
223 IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel
, band
);
227 EXPORT_SYMBOL(iwlcore_set_rxon_channel
);
229 static void iwlcore_init_hw(struct iwl_priv
*priv
)
231 struct ieee80211_hw
*hw
= priv
->hw
;
232 hw
->rate_control_algorithm
= "iwl-4965-rs";
234 /* Tell mac80211 and its clients (e.g. Wireless Extensions)
235 * the range of signal quality values that we'll provide.
236 * Negative values for level/noise indicate that we'll provide dBm.
237 * For WE, at least, non-0 values here *enable* display of values
238 * in app (iwconfig). */
239 hw
->max_rssi
= -20; /* signal level, negative indicates dBm */
240 hw
->max_noise
= -20; /* noise level, negative indicates dBm */
241 hw
->max_signal
= 100; /* link quality indication (%) */
243 /* Tell mac80211 our Tx characteristics */
244 hw
->flags
= IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE
;
246 /* Default value; 4 EDCA QOS priorities */
248 #ifdef CONFIG_IWL4965_HT
249 /* Enhanced value; more queues, to support 11n aggregation */
251 #endif /* CONFIG_IWL4965_HT */
254 int iwl_setup(struct iwl_priv
*priv
)
257 iwlcore_init_hw(priv
);
258 ret
= priv
->cfg
->ops
->lib
->init_drv(priv
);
261 EXPORT_SYMBOL(iwl_setup
);
263 /* Low level driver call this function to update iwlcore with
266 int iwlcore_low_level_notify(struct iwl_priv
*priv
,
267 enum iwlcore_card_notify notify
)
271 case IWLCORE_INIT_EVT
:
272 ret
= iwl_rfkill_init(priv
);
274 IWL_ERROR("Unable to initialize RFKILL system. "
275 "Ignoring error: %d\n", ret
);
276 iwl_power_initialize(priv
);
278 case IWLCORE_START_EVT
:
279 iwl_power_update_mode(priv
, 1);
281 case IWLCORE_STOP_EVT
:
283 case IWLCORE_REMOVE_EVT
:
284 iwl_rfkill_unregister(priv
);
290 EXPORT_SYMBOL(iwlcore_low_level_notify
);
292 int iwl_send_statistics_request(struct iwl_priv
*priv
, u8 flags
)
295 struct iwl_host_cmd cmd
= {
296 .id
= REPLY_STATISTICS_CMD
,
298 .len
= sizeof(stat_flags
),
299 .data
= (u8
*) &stat_flags
,
301 return iwl_send_cmd(priv
, &cmd
);
303 EXPORT_SYMBOL(iwl_send_statistics_request
);