~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/net/wireless/iwlegacy/iwl-4965.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 *
 
3
 * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify it
 
6
 * under the terms of version 2 of the GNU General Public License as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but WITHOUT
 
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
12
 * more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along with
 
15
 * this program; if not, write to the Free Software Foundation, Inc.,
 
16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 
17
 *
 
18
 * The full GNU General Public License is included in this distribution in the
 
19
 * file called LICENSE.
 
20
 *
 
21
 * Contact Information:
 
22
 *  Intel Linux Wireless <ilw@linux.intel.com>
 
23
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
24
 *
 
25
 *****************************************************************************/
 
26
 
 
27
#include <linux/kernel.h>
 
28
#include <linux/module.h>
 
29
#include <linux/init.h>
 
30
#include <linux/pci.h>
 
31
#include <linux/dma-mapping.h>
 
32
#include <linux/delay.h>
 
33
#include <linux/sched.h>
 
34
#include <linux/skbuff.h>
 
35
#include <linux/netdevice.h>
 
36
#include <linux/wireless.h>
 
37
#include <net/mac80211.h>
 
38
#include <linux/etherdevice.h>
 
39
#include <asm/unaligned.h>
 
40
 
 
41
#include "iwl-eeprom.h"
 
42
#include "iwl-dev.h"
 
43
#include "iwl-core.h"
 
44
#include "iwl-io.h"
 
45
#include "iwl-helpers.h"
 
46
#include "iwl-4965-calib.h"
 
47
#include "iwl-sta.h"
 
48
#include "iwl-4965-led.h"
 
49
#include "iwl-4965.h"
 
50
#include "iwl-4965-debugfs.h"
 
51
 
 
52
static int iwl4965_send_tx_power(struct iwl_priv *priv);
 
53
static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
 
54
 
 
55
/* Highest firmware API version supported */
 
56
#define IWL4965_UCODE_API_MAX 2
 
57
 
 
58
/* Lowest firmware API version supported */
 
59
#define IWL4965_UCODE_API_MIN 2
 
60
 
 
61
#define IWL4965_FW_PRE "iwlwifi-4965-"
 
62
#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode"
 
63
#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)
 
64
 
 
65
/* check contents of special bootstrap uCode SRAM */
 
66
static int iwl4965_verify_bsm(struct iwl_priv *priv)
 
67
{
 
68
        __le32 *image = priv->ucode_boot.v_addr;
 
69
        u32 len = priv->ucode_boot.len;
 
70
        u32 reg;
 
71
        u32 val;
 
72
 
 
73
        IWL_DEBUG_INFO(priv, "Begin verify bsm\n");
 
74
 
 
75
        /* verify BSM SRAM contents */
 
76
        val = iwl_legacy_read_prph(priv, BSM_WR_DWCOUNT_REG);
 
77
        for (reg = BSM_SRAM_LOWER_BOUND;
 
78
             reg < BSM_SRAM_LOWER_BOUND + len;
 
79
             reg += sizeof(u32), image++) {
 
80
                val = iwl_legacy_read_prph(priv, reg);
 
81
                if (val != le32_to_cpu(*image)) {
 
82
                        IWL_ERR(priv, "BSM uCode verification failed at "
 
83
                                  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
 
84
                                  BSM_SRAM_LOWER_BOUND,
 
85
                                  reg - BSM_SRAM_LOWER_BOUND, len,
 
86
                                  val, le32_to_cpu(*image));
 
87
                        return -EIO;
 
88
                }
 
89
        }
 
90
 
 
91
        IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n");
 
92
 
 
93
        return 0;
 
94
}
 
95
 
 
96
/**
 
97
 * iwl4965_load_bsm - Load bootstrap instructions
 
98
 *
 
99
 * BSM operation:
 
100
 *
 
101
 * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
 
102
 * in special SRAM that does not power down during RFKILL.  When powering back
 
103
 * up after power-saving sleeps (or during initial uCode load), the BSM loads
 
104
 * the bootstrap program into the on-board processor, and starts it.
 
105
 *
 
106
 * The bootstrap program loads (via DMA) instructions and data for a new
 
107
 * program from host DRAM locations indicated by the host driver in the
 
108
 * BSM_DRAM_* registers.  Once the new program is loaded, it starts
 
109
 * automatically.
 
110
 *
 
111
 * When initializing the NIC, the host driver points the BSM to the
 
112
 * "initialize" uCode image.  This uCode sets up some internal data, then
 
113
 * notifies host via "initialize alive" that it is complete.
 
114
 *
 
115
 * The host then replaces the BSM_DRAM_* pointer values to point to the
 
116
 * normal runtime uCode instructions and a backup uCode data cache buffer
 
117
 * (filled initially with starting data values for the on-board processor),
 
118
 * then triggers the "initialize" uCode to load and launch the runtime uCode,
 
119
 * which begins normal operation.
 
120
 *
 
121
 * When doing a power-save shutdown, runtime uCode saves data SRAM into
 
122
 * the backup data cache in DRAM before SRAM is powered down.
 
123
 *
 
124
 * When powering back up, the BSM loads the bootstrap program.  This reloads
 
125
 * the runtime uCode instructions and the backup data cache into SRAM,
 
126
 * and re-launches the runtime uCode from where it left off.
 
127
 */
 
128
static int iwl4965_load_bsm(struct iwl_priv *priv)
 
129
{
 
130
        __le32 *image = priv->ucode_boot.v_addr;
 
131
        u32 len = priv->ucode_boot.len;
 
132
        dma_addr_t pinst;
 
133
        dma_addr_t pdata;
 
134
        u32 inst_len;
 
135
        u32 data_len;
 
136
        int i;
 
137
        u32 done;
 
138
        u32 reg_offset;
 
139
        int ret;
 
140
 
 
141
        IWL_DEBUG_INFO(priv, "Begin load bsm\n");
 
142
 
 
143
        priv->ucode_type = UCODE_RT;
 
144
 
 
145
        /* make sure bootstrap program is no larger than BSM's SRAM size */
 
146
        if (len > IWL49_MAX_BSM_SIZE)
 
147
                return -EINVAL;
 
148
 
 
149
        /* Tell bootstrap uCode where to find the "Initialize" uCode
 
150
         *   in host DRAM ... host DRAM physical address bits 35:4 for 4965.
 
151
         * NOTE:  iwl_init_alive_start() will replace these values,
 
152
         *        after the "initialize" uCode has run, to point to
 
153
         *        runtime/protocol instructions and backup data cache.
 
154
         */
 
155
        pinst = priv->ucode_init.p_addr >> 4;
 
156
        pdata = priv->ucode_init_data.p_addr >> 4;
 
157
        inst_len = priv->ucode_init.len;
 
158
        data_len = priv->ucode_init_data.len;
 
159
 
 
160
        iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
 
161
        iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
 
162
        iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
 
163
        iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
 
164
 
 
165
        /* Fill BSM memory with bootstrap instructions */
 
166
        for (reg_offset = BSM_SRAM_LOWER_BOUND;
 
167
             reg_offset < BSM_SRAM_LOWER_BOUND + len;
 
168
             reg_offset += sizeof(u32), image++)
 
169
                _iwl_legacy_write_prph(priv, reg_offset, le32_to_cpu(*image));
 
170
 
 
171
        ret = iwl4965_verify_bsm(priv);
 
172
        if (ret)
 
173
                return ret;
 
174
 
 
175
        /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
 
176
        iwl_legacy_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
 
177
        iwl_legacy_write_prph(priv,
 
178
                        BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND);
 
179
        iwl_legacy_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
 
180
 
 
181
        /* Load bootstrap code into instruction SRAM now,
 
182
         *   to prepare to load "initialize" uCode */
 
183
        iwl_legacy_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
 
184
 
 
185
        /* Wait for load of bootstrap uCode to finish */
 
186
        for (i = 0; i < 100; i++) {
 
187
                done = iwl_legacy_read_prph(priv, BSM_WR_CTRL_REG);
 
188
                if (!(done & BSM_WR_CTRL_REG_BIT_START))
 
189
                        break;
 
190
                udelay(10);
 
191
        }
 
192
        if (i < 100)
 
193
                IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
 
194
        else {
 
195
                IWL_ERR(priv, "BSM write did not complete!\n");
 
196
                return -EIO;
 
197
        }
 
198
 
 
199
        /* Enable future boot loads whenever power management unit triggers it
 
200
         *   (e.g. when powering back up after power-save shutdown) */
 
201
        iwl_legacy_write_prph(priv,
 
202
                        BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
 
203
 
 
204
 
 
205
        return 0;
 
206
}
 
207
 
 
208
/**
 
209
 * iwl4965_set_ucode_ptrs - Set uCode address location
 
210
 *
 
211
 * Tell initialization uCode where to find runtime uCode.
 
212
 *
 
213
 * BSM registers initially contain pointers to initialization uCode.
 
214
 * We need to replace them to load runtime uCode inst and data,
 
215
 * and to save runtime data when powering down.
 
216
 */
 
217
static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
 
218
{
 
219
        dma_addr_t pinst;
 
220
        dma_addr_t pdata;
 
221
        int ret = 0;
 
222
 
 
223
        /* bits 35:4 for 4965 */
 
224
        pinst = priv->ucode_code.p_addr >> 4;
 
225
        pdata = priv->ucode_data_backup.p_addr >> 4;
 
226
 
 
227
        /* Tell bootstrap uCode where to find image to load */
 
228
        iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
 
229
        iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
 
230
        iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
 
231
                                 priv->ucode_data.len);
 
232
 
 
233
        /* Inst byte count must be last to set up, bit 31 signals uCode
 
234
         *   that all new ptr/size info is in place */
 
235
        iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
 
236
                                 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
 
237
        IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
 
238
 
 
239
        return ret;
 
240
}
 
241
 
 
242
/**
 
243
 * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
 
244
 *
 
245
 * Called after REPLY_ALIVE notification received from "initialize" uCode.
 
246
 *
 
247
 * The 4965 "initialize" ALIVE reply contains calibration data for:
 
248
 *   Voltage, temperature, and MIMO tx gain correction, now stored in priv
 
249
 *   (3945 does not contain this data).
 
250
 *
 
251
 * Tell "initialize" uCode to go ahead and load the runtime uCode.
 
252
*/
 
253
static void iwl4965_init_alive_start(struct iwl_priv *priv)
 
254
{
 
255
        /* Bootstrap uCode has loaded initialize uCode ... verify inst image.
 
256
         * This is a paranoid check, because we would not have gotten the
 
257
         * "initialize" alive if code weren't properly loaded.  */
 
258
        if (iwl4965_verify_ucode(priv)) {
 
259
                /* Runtime instruction load was bad;
 
260
                 * take it all the way back down so we can try again */
 
261
                IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
 
262
                goto restart;
 
263
        }
 
264
 
 
265
        /* Calculate temperature */
 
266
        priv->temperature = iwl4965_hw_get_temperature(priv);
 
267
 
 
268
        /* Send pointers to protocol/runtime uCode image ... init code will
 
269
         * load and launch runtime uCode, which will send us another "Alive"
 
270
         * notification. */
 
271
        IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
 
272
        if (iwl4965_set_ucode_ptrs(priv)) {
 
273
                /* Runtime instruction load won't happen;
 
274
                 * take it all the way back down so we can try again */
 
275
                IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
 
276
                goto restart;
 
277
        }
 
278
        return;
 
279
 
 
280
restart:
 
281
        queue_work(priv->workqueue, &priv->restart);
 
282
}
 
283
 
 
284
static bool iw4965_is_ht40_channel(__le32 rxon_flags)
 
285
{
 
286
        int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK)
 
287
                                    >> RXON_FLG_CHANNEL_MODE_POS;
 
288
        return ((chan_mod == CHANNEL_MODE_PURE_40) ||
 
289
                  (chan_mod == CHANNEL_MODE_MIXED));
 
290
}
 
291
 
 
292
static void iwl4965_nic_config(struct iwl_priv *priv)
 
293
{
 
294
        unsigned long flags;
 
295
        u16 radio_cfg;
 
296
 
 
297
        spin_lock_irqsave(&priv->lock, flags);
 
298
 
 
299
        radio_cfg = iwl_legacy_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
 
300
 
 
301
        /* write radio config values to register */
 
302
        if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) == EEPROM_4965_RF_CFG_TYPE_MAX)
 
303
                iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
 
304
                            EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
 
305
                            EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
 
306
                            EEPROM_RF_CFG_DASH_MSK(radio_cfg));
 
307
 
 
308
        /* set CSR_HW_CONFIG_REG for uCode use */
 
309
        iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
 
310
                    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
 
311
                    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
 
312
 
 
313
        priv->calib_info = (struct iwl_eeprom_calib_info *)
 
314
                iwl_legacy_eeprom_query_addr(priv,
 
315
                                EEPROM_4965_CALIB_TXPOWER_OFFSET);
 
316
 
 
317
        spin_unlock_irqrestore(&priv->lock, flags);
 
318
}
 
319
 
 
320
/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
 
321
 * Called after every association, but this runs only once!
 
322
 *  ... once chain noise is calibrated the first time, it's good forever.  */
 
323
static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
 
324
{
 
325
        struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
 
326
 
 
327
        if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
 
328
            iwl_legacy_is_any_associated(priv)) {
 
329
                struct iwl_calib_diff_gain_cmd cmd;
 
330
 
 
331
                /* clear data for chain noise calibration algorithm */
 
332
                data->chain_noise_a = 0;
 
333
                data->chain_noise_b = 0;
 
334
                data->chain_noise_c = 0;
 
335
                data->chain_signal_a = 0;
 
336
                data->chain_signal_b = 0;
 
337
                data->chain_signal_c = 0;
 
338
                data->beacon_count = 0;
 
339
 
 
340
                memset(&cmd, 0, sizeof(cmd));
 
341
                cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
 
342
                cmd.diff_gain_a = 0;
 
343
                cmd.diff_gain_b = 0;
 
344
                cmd.diff_gain_c = 0;
 
345
                if (iwl_legacy_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
 
346
                                 sizeof(cmd), &cmd))
 
347
                        IWL_ERR(priv,
 
348
                                "Could not send REPLY_PHY_CALIBRATION_CMD\n");
 
349
                data->state = IWL_CHAIN_NOISE_ACCUMULATE;
 
350
                IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
 
351
        }
 
352
}
 
353
 
 
354
static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
 
355
        .min_nrg_cck = 97,
 
356
        .max_nrg_cck = 0, /* not used, set to 0 */
 
357
 
 
358
        .auto_corr_min_ofdm = 85,
 
359
        .auto_corr_min_ofdm_mrc = 170,
 
360
        .auto_corr_min_ofdm_x1 = 105,
 
361
        .auto_corr_min_ofdm_mrc_x1 = 220,
 
362
 
 
363
        .auto_corr_max_ofdm = 120,
 
364
        .auto_corr_max_ofdm_mrc = 210,
 
365
        .auto_corr_max_ofdm_x1 = 140,
 
366
        .auto_corr_max_ofdm_mrc_x1 = 270,
 
367
 
 
368
        .auto_corr_min_cck = 125,
 
369
        .auto_corr_max_cck = 200,
 
370
        .auto_corr_min_cck_mrc = 200,
 
371
        .auto_corr_max_cck_mrc = 400,
 
372
 
 
373
        .nrg_th_cck = 100,
 
374
        .nrg_th_ofdm = 100,
 
375
 
 
376
        .barker_corr_th_min = 190,
 
377
        .barker_corr_th_min_mrc = 390,
 
378
        .nrg_th_cca = 62,
 
379
};
 
380
 
 
381
static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
 
382
{
 
383
        /* want Kelvin */
 
384
        priv->hw_params.ct_kill_threshold =
 
385
                CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
 
386
}
 
387
 
 
388
/**
 
389
 * iwl4965_hw_set_hw_params
 
390
 *
 
391
 * Called when initializing driver
 
392
 */
 
393
static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
 
394
{
 
395
        if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
 
396
            priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
 
397
                priv->cfg->base_params->num_of_queues =
 
398
                        priv->cfg->mod_params->num_of_queues;
 
399
 
 
400
        priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
 
401
        priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
 
402
        priv->hw_params.scd_bc_tbls_size =
 
403
                        priv->cfg->base_params->num_of_queues *
 
404
                        sizeof(struct iwl4965_scd_bc_tbl);
 
405
        priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
 
406
        priv->hw_params.max_stations = IWL4965_STATION_COUNT;
 
407
        priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID;
 
408
        priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
 
409
        priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
 
410
        priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
 
411
        priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
 
412
 
 
413
        priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
414
 
 
415
        priv->hw_params.tx_chains_num = iwl4965_num_of_ant(priv->cfg->valid_tx_ant);
 
416
        priv->hw_params.rx_chains_num = iwl4965_num_of_ant(priv->cfg->valid_rx_ant);
 
417
        priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
 
418
        priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
 
419
 
 
420
        iwl4965_set_ct_threshold(priv);
 
421
 
 
422
        priv->hw_params.sens = &iwl4965_sensitivity;
 
423
        priv->hw_params.beacon_time_tsf_bits = IWL4965_EXT_BEACON_TIME_POS;
 
424
 
 
425
        return 0;
 
426
}
 
427
 
 
428
static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res)
 
429
{
 
430
        s32 sign = 1;
 
431
 
 
432
        if (num < 0) {
 
433
                sign = -sign;
 
434
                num = -num;
 
435
        }
 
436
        if (denom < 0) {
 
437
                sign = -sign;
 
438
                denom = -denom;
 
439
        }
 
440
        *res = 1;
 
441
        *res = ((num * 2 + denom) / (denom * 2)) * sign;
 
442
 
 
443
        return 1;
 
444
}
 
445
 
 
446
/**
 
447
 * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower
 
448
 *
 
449
 * Determines power supply voltage compensation for txpower calculations.
 
450
 * Returns number of 1/2-dB steps to subtract from gain table index,
 
451
 * to compensate for difference between power supply voltage during
 
452
 * factory measurements, vs. current power supply voltage.
 
453
 *
 
454
 * Voltage indication is higher for lower voltage.
 
455
 * Lower voltage requires more gain (lower gain table index).
 
456
 */
 
457
static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
 
458
                                            s32 current_voltage)
 
459
{
 
460
        s32 comp = 0;
 
461
 
 
462
        if ((TX_POWER_IWL_ILLEGAL_VOLTAGE == eeprom_voltage) ||
 
463
            (TX_POWER_IWL_ILLEGAL_VOLTAGE == current_voltage))
 
464
                return 0;
 
465
 
 
466
        iwl4965_math_div_round(current_voltage - eeprom_voltage,
 
467
                               TX_POWER_IWL_VOLTAGE_CODES_PER_03V, &comp);
 
468
 
 
469
        if (current_voltage > eeprom_voltage)
 
470
                comp *= 2;
 
471
        if ((comp < -2) || (comp > 2))
 
472
                comp = 0;
 
473
 
 
474
        return comp;
 
475
}
 
476
 
 
477
static s32 iwl4965_get_tx_atten_grp(u16 channel)
 
478
{
 
479
        if (channel >= CALIB_IWL_TX_ATTEN_GR5_FCH &&
 
480
            channel <= CALIB_IWL_TX_ATTEN_GR5_LCH)
 
481
                return CALIB_CH_GROUP_5;
 
482
 
 
483
        if (channel >= CALIB_IWL_TX_ATTEN_GR1_FCH &&
 
484
            channel <= CALIB_IWL_TX_ATTEN_GR1_LCH)
 
485
                return CALIB_CH_GROUP_1;
 
486
 
 
487
        if (channel >= CALIB_IWL_TX_ATTEN_GR2_FCH &&
 
488
            channel <= CALIB_IWL_TX_ATTEN_GR2_LCH)
 
489
                return CALIB_CH_GROUP_2;
 
490
 
 
491
        if (channel >= CALIB_IWL_TX_ATTEN_GR3_FCH &&
 
492
            channel <= CALIB_IWL_TX_ATTEN_GR3_LCH)
 
493
                return CALIB_CH_GROUP_3;
 
494
 
 
495
        if (channel >= CALIB_IWL_TX_ATTEN_GR4_FCH &&
 
496
            channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
 
497
                return CALIB_CH_GROUP_4;
 
498
 
 
499
        return -1;
 
500
}
 
501
 
 
502
static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
 
503
{
 
504
        s32 b = -1;
 
505
 
 
506
        for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) {
 
507
                if (priv->calib_info->band_info[b].ch_from == 0)
 
508
                        continue;
 
509
 
 
510
                if ((channel >= priv->calib_info->band_info[b].ch_from)
 
511
                    && (channel <= priv->calib_info->band_info[b].ch_to))
 
512
                        break;
 
513
        }
 
514
 
 
515
        return b;
 
516
}
 
517
 
 
518
static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
 
519
{
 
520
        s32 val;
 
521
 
 
522
        if (x2 == x1)
 
523
                return y1;
 
524
        else {
 
525
                iwl4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val);
 
526
                return val + y2;
 
527
        }
 
528
}
 
529
 
 
530
/**
 
531
 * iwl4965_interpolate_chan - Interpolate factory measurements for one channel
 
532
 *
 
533
 * Interpolates factory measurements from the two sample channels within a
 
534
 * sub-band, to apply to channel of interest.  Interpolation is proportional to
 
535
 * differences in channel frequencies, which is proportional to differences
 
536
 * in channel number.
 
537
 */
 
538
static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
 
539
                                    struct iwl_eeprom_calib_ch_info *chan_info)
 
540
{
 
541
        s32 s = -1;
 
542
        u32 c;
 
543
        u32 m;
 
544
        const struct iwl_eeprom_calib_measure *m1;
 
545
        const struct iwl_eeprom_calib_measure *m2;
 
546
        struct iwl_eeprom_calib_measure *omeas;
 
547
        u32 ch_i1;
 
548
        u32 ch_i2;
 
549
 
 
550
        s = iwl4965_get_sub_band(priv, channel);
 
551
        if (s >= EEPROM_TX_POWER_BANDS) {
 
552
                IWL_ERR(priv, "Tx Power can not find channel %d\n", channel);
 
553
                return -1;
 
554
        }
 
555
 
 
556
        ch_i1 = priv->calib_info->band_info[s].ch1.ch_num;
 
557
        ch_i2 = priv->calib_info->band_info[s].ch2.ch_num;
 
558
        chan_info->ch_num = (u8) channel;
 
559
 
 
560
        IWL_DEBUG_TXPOWER(priv, "channel %d subband %d factory cal ch %d & %d\n",
 
561
                          channel, s, ch_i1, ch_i2);
 
562
 
 
563
        for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) {
 
564
                for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) {
 
565
                        m1 = &(priv->calib_info->band_info[s].ch1.
 
566
                               measurements[c][m]);
 
567
                        m2 = &(priv->calib_info->band_info[s].ch2.
 
568
                               measurements[c][m]);
 
569
                        omeas = &(chan_info->measurements[c][m]);
 
570
 
 
571
                        omeas->actual_pow =
 
572
                            (u8) iwl4965_interpolate_value(channel, ch_i1,
 
573
                                                           m1->actual_pow,
 
574
                                                           ch_i2,
 
575
                                                           m2->actual_pow);
 
576
                        omeas->gain_idx =
 
577
                            (u8) iwl4965_interpolate_value(channel, ch_i1,
 
578
                                                           m1->gain_idx, ch_i2,
 
579
                                                           m2->gain_idx);
 
580
                        omeas->temperature =
 
581
                            (u8) iwl4965_interpolate_value(channel, ch_i1,
 
582
                                                           m1->temperature,
 
583
                                                           ch_i2,
 
584
                                                           m2->temperature);
 
585
                        omeas->pa_det =
 
586
                            (s8) iwl4965_interpolate_value(channel, ch_i1,
 
587
                                                           m1->pa_det, ch_i2,
 
588
                                                           m2->pa_det);
 
589
 
 
590
                        IWL_DEBUG_TXPOWER(priv,
 
591
                                "chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m,
 
592
                                m1->actual_pow, m2->actual_pow, omeas->actual_pow);
 
593
                        IWL_DEBUG_TXPOWER(priv,
 
594
                                "chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m,
 
595
                                m1->gain_idx, m2->gain_idx, omeas->gain_idx);
 
596
                        IWL_DEBUG_TXPOWER(priv,
 
597
                                "chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m,
 
598
                                m1->pa_det, m2->pa_det, omeas->pa_det);
 
599
                        IWL_DEBUG_TXPOWER(priv,
 
600
                                "chain %d meas %d  T1=%d  T2=%d  T=%d\n", c, m,
 
601
                                m1->temperature, m2->temperature,
 
602
                                omeas->temperature);
 
603
                }
 
604
        }
 
605
 
 
606
        return 0;
 
607
}
 
608
 
 
609
/* bit-rate-dependent table to prevent Tx distortion, in half-dB units,
 
610
 * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */
 
611
static s32 back_off_table[] = {
 
612
        10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 20 MHz */
 
613
        10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 20 MHz */
 
614
        10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 40 MHz */
 
615
        10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 40 MHz */
 
616
        10                      /* CCK */
 
617
};
 
618
 
 
619
/* Thermal compensation values for txpower for various frequency ranges ...
 
620
 *   ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */
 
621
static struct iwl4965_txpower_comp_entry {
 
622
        s32 degrees_per_05db_a;
 
623
        s32 degrees_per_05db_a_denom;
 
624
} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = {
 
625
        {9, 2},                 /* group 0 5.2, ch  34-43 */
 
626
        {4, 1},                 /* group 1 5.2, ch  44-70 */
 
627
        {4, 1},                 /* group 2 5.2, ch  71-124 */
 
628
        {4, 1},                 /* group 3 5.2, ch 125-200 */
 
629
        {3, 1}                  /* group 4 2.4, ch   all */
 
630
};
 
631
 
 
632
static s32 get_min_power_index(s32 rate_power_index, u32 band)
 
633
{
 
634
        if (!band) {
 
635
                if ((rate_power_index & 7) <= 4)
 
636
                        return MIN_TX_GAIN_INDEX_52GHZ_EXT;
 
637
        }
 
638
        return MIN_TX_GAIN_INDEX;
 
639
}
 
640
 
 
641
struct gain_entry {
 
642
        u8 dsp;
 
643
        u8 radio;
 
644
};
 
645
 
 
646
static const struct gain_entry gain_table[2][108] = {
 
647
        /* 5.2GHz power gain index table */
 
648
        {
 
649
         {123, 0x3F},           /* highest txpower */
 
650
         {117, 0x3F},
 
651
         {110, 0x3F},
 
652
         {104, 0x3F},
 
653
         {98, 0x3F},
 
654
         {110, 0x3E},
 
655
         {104, 0x3E},
 
656
         {98, 0x3E},
 
657
         {110, 0x3D},
 
658
         {104, 0x3D},
 
659
         {98, 0x3D},
 
660
         {110, 0x3C},
 
661
         {104, 0x3C},
 
662
         {98, 0x3C},
 
663
         {110, 0x3B},
 
664
         {104, 0x3B},
 
665
         {98, 0x3B},
 
666
         {110, 0x3A},
 
667
         {104, 0x3A},
 
668
         {98, 0x3A},
 
669
         {110, 0x39},
 
670
         {104, 0x39},
 
671
         {98, 0x39},
 
672
         {110, 0x38},
 
673
         {104, 0x38},
 
674
         {98, 0x38},
 
675
         {110, 0x37},
 
676
         {104, 0x37},
 
677
         {98, 0x37},
 
678
         {110, 0x36},
 
679
         {104, 0x36},
 
680
         {98, 0x36},
 
681
         {110, 0x35},
 
682
         {104, 0x35},
 
683
         {98, 0x35},
 
684
         {110, 0x34},
 
685
         {104, 0x34},
 
686
         {98, 0x34},
 
687
         {110, 0x33},
 
688
         {104, 0x33},
 
689
         {98, 0x33},
 
690
         {110, 0x32},
 
691
         {104, 0x32},
 
692
         {98, 0x32},
 
693
         {110, 0x31},
 
694
         {104, 0x31},
 
695
         {98, 0x31},
 
696
         {110, 0x30},
 
697
         {104, 0x30},
 
698
         {98, 0x30},
 
699
         {110, 0x25},
 
700
         {104, 0x25},
 
701
         {98, 0x25},
 
702
         {110, 0x24},
 
703
         {104, 0x24},
 
704
         {98, 0x24},
 
705
         {110, 0x23},
 
706
         {104, 0x23},
 
707
         {98, 0x23},
 
708
         {110, 0x22},
 
709
         {104, 0x18},
 
710
         {98, 0x18},
 
711
         {110, 0x17},
 
712
         {104, 0x17},
 
713
         {98, 0x17},
 
714
         {110, 0x16},
 
715
         {104, 0x16},
 
716
         {98, 0x16},
 
717
         {110, 0x15},
 
718
         {104, 0x15},
 
719
         {98, 0x15},
 
720
         {110, 0x14},
 
721
         {104, 0x14},
 
722
         {98, 0x14},
 
723
         {110, 0x13},
 
724
         {104, 0x13},
 
725
         {98, 0x13},
 
726
         {110, 0x12},
 
727
         {104, 0x08},
 
728
         {98, 0x08},
 
729
         {110, 0x07},
 
730
         {104, 0x07},
 
731
         {98, 0x07},
 
732
         {110, 0x06},
 
733
         {104, 0x06},
 
734
         {98, 0x06},
 
735
         {110, 0x05},
 
736
         {104, 0x05},
 
737
         {98, 0x05},
 
738
         {110, 0x04},
 
739
         {104, 0x04},
 
740
         {98, 0x04},
 
741
         {110, 0x03},
 
742
         {104, 0x03},
 
743
         {98, 0x03},
 
744
         {110, 0x02},
 
745
         {104, 0x02},
 
746
         {98, 0x02},
 
747
         {110, 0x01},
 
748
         {104, 0x01},
 
749
         {98, 0x01},
 
750
         {110, 0x00},
 
751
         {104, 0x00},
 
752
         {98, 0x00},
 
753
         {93, 0x00},
 
754
         {88, 0x00},
 
755
         {83, 0x00},
 
756
         {78, 0x00},
 
757
         },
 
758
        /* 2.4GHz power gain index table */
 
759
        {
 
760
         {110, 0x3f},           /* highest txpower */
 
761
         {104, 0x3f},
 
762
         {98, 0x3f},
 
763
         {110, 0x3e},
 
764
         {104, 0x3e},
 
765
         {98, 0x3e},
 
766
         {110, 0x3d},
 
767
         {104, 0x3d},
 
768
         {98, 0x3d},
 
769
         {110, 0x3c},
 
770
         {104, 0x3c},
 
771
         {98, 0x3c},
 
772
         {110, 0x3b},
 
773
         {104, 0x3b},
 
774
         {98, 0x3b},
 
775
         {110, 0x3a},
 
776
         {104, 0x3a},
 
777
         {98, 0x3a},
 
778
         {110, 0x39},
 
779
         {104, 0x39},
 
780
         {98, 0x39},
 
781
         {110, 0x38},
 
782
         {104, 0x38},
 
783
         {98, 0x38},
 
784
         {110, 0x37},
 
785
         {104, 0x37},
 
786
         {98, 0x37},
 
787
         {110, 0x36},
 
788
         {104, 0x36},
 
789
         {98, 0x36},
 
790
         {110, 0x35},
 
791
         {104, 0x35},
 
792
         {98, 0x35},
 
793
         {110, 0x34},
 
794
         {104, 0x34},
 
795
         {98, 0x34},
 
796
         {110, 0x33},
 
797
         {104, 0x33},
 
798
         {98, 0x33},
 
799
         {110, 0x32},
 
800
         {104, 0x32},
 
801
         {98, 0x32},
 
802
         {110, 0x31},
 
803
         {104, 0x31},
 
804
         {98, 0x31},
 
805
         {110, 0x30},
 
806
         {104, 0x30},
 
807
         {98, 0x30},
 
808
         {110, 0x6},
 
809
         {104, 0x6},
 
810
         {98, 0x6},
 
811
         {110, 0x5},
 
812
         {104, 0x5},
 
813
         {98, 0x5},
 
814
         {110, 0x4},
 
815
         {104, 0x4},
 
816
         {98, 0x4},
 
817
         {110, 0x3},
 
818
         {104, 0x3},
 
819
         {98, 0x3},
 
820
         {110, 0x2},
 
821
         {104, 0x2},
 
822
         {98, 0x2},
 
823
         {110, 0x1},
 
824
         {104, 0x1},
 
825
         {98, 0x1},
 
826
         {110, 0x0},
 
827
         {104, 0x0},
 
828
         {98, 0x0},
 
829
         {97, 0},
 
830
         {96, 0},
 
831
         {95, 0},
 
832
         {94, 0},
 
833
         {93, 0},
 
834
         {92, 0},
 
835
         {91, 0},
 
836
         {90, 0},
 
837
         {89, 0},
 
838
         {88, 0},
 
839
         {87, 0},
 
840
         {86, 0},
 
841
         {85, 0},
 
842
         {84, 0},
 
843
         {83, 0},
 
844
         {82, 0},
 
845
         {81, 0},
 
846
         {80, 0},
 
847
         {79, 0},
 
848
         {78, 0},
 
849
         {77, 0},
 
850
         {76, 0},
 
851
         {75, 0},
 
852
         {74, 0},
 
853
         {73, 0},
 
854
         {72, 0},
 
855
         {71, 0},
 
856
         {70, 0},
 
857
         {69, 0},
 
858
         {68, 0},
 
859
         {67, 0},
 
860
         {66, 0},
 
861
         {65, 0},
 
862
         {64, 0},
 
863
         {63, 0},
 
864
         {62, 0},
 
865
         {61, 0},
 
866
         {60, 0},
 
867
         {59, 0},
 
868
         }
 
869
};
 
870
 
 
871
static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
 
872
                                    u8 is_ht40, u8 ctrl_chan_high,
 
873
                                    struct iwl4965_tx_power_db *tx_power_tbl)
 
874
{
 
875
        u8 saturation_power;
 
876
        s32 target_power;
 
877
        s32 user_target_power;
 
878
        s32 power_limit;
 
879
        s32 current_temp;
 
880
        s32 reg_limit;
 
881
        s32 current_regulatory;
 
882
        s32 txatten_grp = CALIB_CH_GROUP_MAX;
 
883
        int i;
 
884
        int c;
 
885
        const struct iwl_channel_info *ch_info = NULL;
 
886
        struct iwl_eeprom_calib_ch_info ch_eeprom_info;
 
887
        const struct iwl_eeprom_calib_measure *measurement;
 
888
        s16 voltage;
 
889
        s32 init_voltage;
 
890
        s32 voltage_compensation;
 
891
        s32 degrees_per_05db_num;
 
892
        s32 degrees_per_05db_denom;
 
893
        s32 factory_temp;
 
894
        s32 temperature_comp[2];
 
895
        s32 factory_gain_index[2];
 
896
        s32 factory_actual_pwr[2];
 
897
        s32 power_index;
 
898
 
 
899
        /* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units
 
900
         *   are used for indexing into txpower table) */
 
901
        user_target_power = 2 * priv->tx_power_user_lmt;
 
902
 
 
903
        /* Get current (RXON) channel, band, width */
 
904
        IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band,
 
905
                          is_ht40);
 
906
 
 
907
        ch_info = iwl_legacy_get_channel_info(priv, priv->band, channel);
 
908
 
 
909
        if (!iwl_legacy_is_channel_valid(ch_info))
 
910
                return -EINVAL;
 
911
 
 
912
        /* get txatten group, used to select 1) thermal txpower adjustment
 
913
         *   and 2) mimo txpower balance between Tx chains. */
 
914
        txatten_grp = iwl4965_get_tx_atten_grp(channel);
 
915
        if (txatten_grp < 0) {
 
916
                IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
 
917
                          channel);
 
918
                return -EINVAL;
 
919
        }
 
920
 
 
921
        IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
 
922
                          channel, txatten_grp);
 
923
 
 
924
        if (is_ht40) {
 
925
                if (ctrl_chan_high)
 
926
                        channel -= 2;
 
927
                else
 
928
                        channel += 2;
 
929
        }
 
930
 
 
931
        /* hardware txpower limits ...
 
932
         * saturation (clipping distortion) txpowers are in half-dBm */
 
933
        if (band)
 
934
                saturation_power = priv->calib_info->saturation_power24;
 
935
        else
 
936
                saturation_power = priv->calib_info->saturation_power52;
 
937
 
 
938
        if (saturation_power < IWL_TX_POWER_SATURATION_MIN ||
 
939
            saturation_power > IWL_TX_POWER_SATURATION_MAX) {
 
940
                if (band)
 
941
                        saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_24;
 
942
                else
 
943
                        saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_52;
 
944
        }
 
945
 
 
946
        /* regulatory txpower limits ... reg_limit values are in half-dBm,
 
947
         *   max_power_avg values are in dBm, convert * 2 */
 
948
        if (is_ht40)
 
949
                reg_limit = ch_info->ht40_max_power_avg * 2;
 
950
        else
 
951
                reg_limit = ch_info->max_power_avg * 2;
 
952
 
 
953
        if ((reg_limit < IWL_TX_POWER_REGULATORY_MIN) ||
 
954
            (reg_limit > IWL_TX_POWER_REGULATORY_MAX)) {
 
955
                if (band)
 
956
                        reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_24;
 
957
                else
 
958
                        reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_52;
 
959
        }
 
960
 
 
961
        /* Interpolate txpower calibration values for this channel,
 
962
         *   based on factory calibration tests on spaced channels. */
 
963
        iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info);
 
964
 
 
965
        /* calculate tx gain adjustment based on power supply voltage */
 
966
        voltage = le16_to_cpu(priv->calib_info->voltage);
 
967
        init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage);
 
968
        voltage_compensation =
 
969
            iwl4965_get_voltage_compensation(voltage, init_voltage);
 
970
 
 
971
        IWL_DEBUG_TXPOWER(priv, "curr volt %d eeprom volt %d volt comp %d\n",
 
972
                          init_voltage,
 
973
                          voltage, voltage_compensation);
 
974
 
 
975
        /* get current temperature (Celsius) */
 
976
        current_temp = max(priv->temperature, IWL_TX_POWER_TEMPERATURE_MIN);
 
977
        current_temp = min(priv->temperature, IWL_TX_POWER_TEMPERATURE_MAX);
 
978
        current_temp = KELVIN_TO_CELSIUS(current_temp);
 
979
 
 
980
        /* select thermal txpower adjustment params, based on channel group
 
981
         *   (same frequency group used for mimo txatten adjustment) */
 
982
        degrees_per_05db_num =
 
983
            tx_power_cmp_tble[txatten_grp].degrees_per_05db_a;
 
984
        degrees_per_05db_denom =
 
985
            tx_power_cmp_tble[txatten_grp].degrees_per_05db_a_denom;
 
986
 
 
987
        /* get per-chain txpower values from factory measurements */
 
988
        for (c = 0; c < 2; c++) {
 
989
                measurement = &ch_eeprom_info.measurements[c][1];
 
990
 
 
991
                /* txgain adjustment (in half-dB steps) based on difference
 
992
                 *   between factory and current temperature */
 
993
                factory_temp = measurement->temperature;
 
994
                iwl4965_math_div_round((current_temp - factory_temp) *
 
995
                                       degrees_per_05db_denom,
 
996
                                       degrees_per_05db_num,
 
997
                                       &temperature_comp[c]);
 
998
 
 
999
                factory_gain_index[c] = measurement->gain_idx;
 
1000
                factory_actual_pwr[c] = measurement->actual_pow;
 
1001
 
 
1002
                IWL_DEBUG_TXPOWER(priv, "chain = %d\n", c);
 
1003
                IWL_DEBUG_TXPOWER(priv, "fctry tmp %d, "
 
1004
                                  "curr tmp %d, comp %d steps\n",
 
1005
                                  factory_temp, current_temp,
 
1006
                                  temperature_comp[c]);
 
1007
 
 
1008
                IWL_DEBUG_TXPOWER(priv, "fctry idx %d, fctry pwr %d\n",
 
1009
                                  factory_gain_index[c],
 
1010
                                  factory_actual_pwr[c]);
 
1011
        }
 
1012
 
 
1013
        /* for each of 33 bit-rates (including 1 for CCK) */
 
1014
        for (i = 0; i < POWER_TABLE_NUM_ENTRIES; i++) {
 
1015
                u8 is_mimo_rate;
 
1016
                union iwl4965_tx_power_dual_stream tx_power;
 
1017
 
 
1018
                /* for mimo, reduce each chain's txpower by half
 
1019
                 * (3dB, 6 steps), so total output power is regulatory
 
1020
                 * compliant. */
 
1021
                if (i & 0x8) {
 
1022
                        current_regulatory = reg_limit -
 
1023
                            IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION;
 
1024
                        is_mimo_rate = 1;
 
1025
                } else {
 
1026
                        current_regulatory = reg_limit;
 
1027
                        is_mimo_rate = 0;
 
1028
                }
 
1029
 
 
1030
                /* find txpower limit, either hardware or regulatory */
 
1031
                power_limit = saturation_power - back_off_table[i];
 
1032
                if (power_limit > current_regulatory)
 
1033
                        power_limit = current_regulatory;
 
1034
 
 
1035
                /* reduce user's txpower request if necessary
 
1036
                 * for this rate on this channel */
 
1037
                target_power = user_target_power;
 
1038
                if (target_power > power_limit)
 
1039
                        target_power = power_limit;
 
1040
 
 
1041
                IWL_DEBUG_TXPOWER(priv, "rate %d sat %d reg %d usr %d tgt %d\n",
 
1042
                                  i, saturation_power - back_off_table[i],
 
1043
                                  current_regulatory, user_target_power,
 
1044
                                  target_power);
 
1045
 
 
1046
                /* for each of 2 Tx chains (radio transmitters) */
 
1047
                for (c = 0; c < 2; c++) {
 
1048
                        s32 atten_value;
 
1049
 
 
1050
                        if (is_mimo_rate)
 
1051
                                atten_value =
 
1052
                                    (s32)le32_to_cpu(priv->card_alive_init.
 
1053
                                    tx_atten[txatten_grp][c]);
 
1054
                        else
 
1055
                                atten_value = 0;
 
1056
 
 
1057
                        /* calculate index; higher index means lower txpower */
 
1058
                        power_index = (u8) (factory_gain_index[c] -
 
1059
                                            (target_power -
 
1060
                                             factory_actual_pwr[c]) -
 
1061
                                            temperature_comp[c] -
 
1062
                                            voltage_compensation +
 
1063
                                            atten_value);
 
1064
 
 
1065
/*                      IWL_DEBUG_TXPOWER(priv, "calculated txpower index %d\n",
 
1066
                                                power_index); */
 
1067
 
 
1068
                        if (power_index < get_min_power_index(i, band))
 
1069
                                power_index = get_min_power_index(i, band);
 
1070
 
 
1071
                        /* adjust 5 GHz index to support negative indexes */
 
1072
                        if (!band)
 
1073
                                power_index += 9;
 
1074
 
 
1075
                        /* CCK, rate 32, reduce txpower for CCK */
 
1076
                        if (i == POWER_TABLE_CCK_ENTRY)
 
1077
                                power_index +=
 
1078
                                    IWL_TX_POWER_CCK_COMPENSATION_C_STEP;
 
1079
 
 
1080
                        /* stay within the table! */
 
1081
                        if (power_index > 107) {
 
1082
                                IWL_WARN(priv, "txpower index %d > 107\n",
 
1083
                                            power_index);
 
1084
                                power_index = 107;
 
1085
                        }
 
1086
                        if (power_index < 0) {
 
1087
                                IWL_WARN(priv, "txpower index %d < 0\n",
 
1088
                                            power_index);
 
1089
                                power_index = 0;
 
1090
                        }
 
1091
 
 
1092
                        /* fill txpower command for this rate/chain */
 
1093
                        tx_power.s.radio_tx_gain[c] =
 
1094
                                gain_table[band][power_index].radio;
 
1095
                        tx_power.s.dsp_predis_atten[c] =
 
1096
                                gain_table[band][power_index].dsp;
 
1097
 
 
1098
                        IWL_DEBUG_TXPOWER(priv, "chain %d mimo %d index %d "
 
1099
                                          "gain 0x%02x dsp %d\n",
 
1100
                                          c, atten_value, power_index,
 
1101
                                        tx_power.s.radio_tx_gain[c],
 
1102
                                        tx_power.s.dsp_predis_atten[c]);
 
1103
                } /* for each chain */
 
1104
 
 
1105
                tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw);
 
1106
 
 
1107
        } /* for each rate */
 
1108
 
 
1109
        return 0;
 
1110
}
 
1111
 
 
1112
/**
 
1113
 * iwl4965_send_tx_power - Configure the TXPOWER level user limit
 
1114
 *
 
1115
 * Uses the active RXON for channel, band, and characteristics (ht40, high)
 
1116
 * The power limit is taken from priv->tx_power_user_lmt.
 
1117
 */
 
1118
static int iwl4965_send_tx_power(struct iwl_priv *priv)
 
1119
{
 
1120
        struct iwl4965_txpowertable_cmd cmd = { 0 };
 
1121
        int ret;
 
1122
        u8 band = 0;
 
1123
        bool is_ht40 = false;
 
1124
        u8 ctrl_chan_high = 0;
 
1125
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
1126
 
 
1127
        if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
 
1128
                      "TX Power requested while scanning!\n"))
 
1129
                return -EAGAIN;
 
1130
 
 
1131
        band = priv->band == IEEE80211_BAND_2GHZ;
 
1132
 
 
1133
        is_ht40 = iw4965_is_ht40_channel(ctx->active.flags);
 
1134
 
 
1135
        if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
 
1136
                ctrl_chan_high = 1;
 
1137
 
 
1138
        cmd.band = band;
 
1139
        cmd.channel = ctx->active.channel;
 
1140
 
 
1141
        ret = iwl4965_fill_txpower_tbl(priv, band,
 
1142
                                le16_to_cpu(ctx->active.channel),
 
1143
                                is_ht40, ctrl_chan_high, &cmd.tx_power);
 
1144
        if (ret)
 
1145
                goto out;
 
1146
 
 
1147
        ret = iwl_legacy_send_cmd_pdu(priv,
 
1148
                         REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
 
1149
 
 
1150
out:
 
1151
        return ret;
 
1152
}
 
1153
 
 
1154
static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
 
1155
                                   struct iwl_rxon_context *ctx)
 
1156
{
 
1157
        int ret = 0;
 
1158
        struct iwl4965_rxon_assoc_cmd rxon_assoc;
 
1159
        const struct iwl_legacy_rxon_cmd *rxon1 = &ctx->staging;
 
1160
        const struct iwl_legacy_rxon_cmd *rxon2 = &ctx->active;
 
1161
 
 
1162
        if ((rxon1->flags == rxon2->flags) &&
 
1163
            (rxon1->filter_flags == rxon2->filter_flags) &&
 
1164
            (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
 
1165
            (rxon1->ofdm_ht_single_stream_basic_rates ==
 
1166
             rxon2->ofdm_ht_single_stream_basic_rates) &&
 
1167
            (rxon1->ofdm_ht_dual_stream_basic_rates ==
 
1168
             rxon2->ofdm_ht_dual_stream_basic_rates) &&
 
1169
            (rxon1->rx_chain == rxon2->rx_chain) &&
 
1170
            (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
 
1171
                IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
 
1172
                return 0;
 
1173
        }
 
1174
 
 
1175
        rxon_assoc.flags = ctx->staging.flags;
 
1176
        rxon_assoc.filter_flags = ctx->staging.filter_flags;
 
1177
        rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
 
1178
        rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
 
1179
        rxon_assoc.reserved = 0;
 
1180
        rxon_assoc.ofdm_ht_single_stream_basic_rates =
 
1181
            ctx->staging.ofdm_ht_single_stream_basic_rates;
 
1182
        rxon_assoc.ofdm_ht_dual_stream_basic_rates =
 
1183
            ctx->staging.ofdm_ht_dual_stream_basic_rates;
 
1184
        rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
 
1185
 
 
1186
        ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
 
1187
                                     sizeof(rxon_assoc), &rxon_assoc, NULL);
 
1188
        if (ret)
 
1189
                return ret;
 
1190
 
 
1191
        return ret;
 
1192
}
 
1193
 
 
1194
static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 
1195
{
 
1196
        /* cast away the const for active_rxon in this function */
 
1197
        struct iwl_legacy_rxon_cmd *active_rxon = (void *)&ctx->active;
 
1198
        int ret;
 
1199
        bool new_assoc =
 
1200
                !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
 
1201
 
 
1202
        if (!iwl_legacy_is_alive(priv))
 
1203
                return -EBUSY;
 
1204
 
 
1205
        if (!ctx->is_active)
 
1206
                return 0;
 
1207
 
 
1208
        /* always get timestamp with Rx frame */
 
1209
        ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
 
1210
 
 
1211
        ret = iwl_legacy_check_rxon_cmd(priv, ctx);
 
1212
        if (ret) {
 
1213
                IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
 
1214
                return -EINVAL;
 
1215
        }
 
1216
 
 
1217
        /*
 
1218
         * receive commit_rxon request
 
1219
         * abort any previous channel switch if still in process
 
1220
         */
 
1221
        if (priv->switch_rxon.switch_in_progress &&
 
1222
            (priv->switch_rxon.channel != ctx->staging.channel)) {
 
1223
                IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
 
1224
                      le16_to_cpu(priv->switch_rxon.channel));
 
1225
                iwl_legacy_chswitch_done(priv, false);
 
1226
        }
 
1227
 
 
1228
        /* If we don't need to send a full RXON, we can use
 
1229
         * iwl_rxon_assoc_cmd which is used to reconfigure filter
 
1230
         * and other flags for the current radio configuration. */
 
1231
        if (!iwl_legacy_full_rxon_required(priv, ctx)) {
 
1232
                ret = iwl_legacy_send_rxon_assoc(priv, ctx);
 
1233
                if (ret) {
 
1234
                        IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
 
1235
                        return ret;
 
1236
                }
 
1237
 
 
1238
                memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
 
1239
                iwl_legacy_print_rx_config_cmd(priv, ctx);
 
1240
                return 0;
 
1241
        }
 
1242
 
 
1243
        /* If we are currently associated and the new config requires
 
1244
         * an RXON_ASSOC and the new config wants the associated mask enabled,
 
1245
         * we must clear the associated from the active configuration
 
1246
         * before we apply the new config */
 
1247
        if (iwl_legacy_is_associated_ctx(ctx) && new_assoc) {
 
1248
                IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
 
1249
                active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 
1250
 
 
1251
                ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
 
1252
                                       sizeof(struct iwl_legacy_rxon_cmd),
 
1253
                                       active_rxon);
 
1254
 
 
1255
                /* If the mask clearing failed then we set
 
1256
                 * active_rxon back to what it was previously */
 
1257
                if (ret) {
 
1258
                        active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
 
1259
                        IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
 
1260
                        return ret;
 
1261
                }
 
1262
                iwl_legacy_clear_ucode_stations(priv, ctx);
 
1263
                iwl_legacy_restore_stations(priv, ctx);
 
1264
                ret = iwl4965_restore_default_wep_keys(priv, ctx);
 
1265
                if (ret) {
 
1266
                        IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
 
1267
                        return ret;
 
1268
                }
 
1269
        }
 
1270
 
 
1271
        IWL_DEBUG_INFO(priv, "Sending RXON\n"
 
1272
                       "* with%s RXON_FILTER_ASSOC_MSK\n"
 
1273
                       "* channel = %d\n"
 
1274
                       "* bssid = %pM\n",
 
1275
                       (new_assoc ? "" : "out"),
 
1276
                       le16_to_cpu(ctx->staging.channel),
 
1277
                       ctx->staging.bssid_addr);
 
1278
 
 
1279
        iwl_legacy_set_rxon_hwcrypto(priv, ctx,
 
1280
                                !priv->cfg->mod_params->sw_crypto);
 
1281
 
 
1282
        /* Apply the new configuration
 
1283
         * RXON unassoc clears the station table in uCode so restoration of
 
1284
         * stations is needed after it (the RXON command) completes
 
1285
         */
 
1286
        if (!new_assoc) {
 
1287
                ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
 
1288
                              sizeof(struct iwl_legacy_rxon_cmd), &ctx->staging);
 
1289
                if (ret) {
 
1290
                        IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
 
1291
                        return ret;
 
1292
                }
 
1293
                IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
 
1294
                memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
 
1295
                iwl_legacy_clear_ucode_stations(priv, ctx);
 
1296
                iwl_legacy_restore_stations(priv, ctx);
 
1297
                ret = iwl4965_restore_default_wep_keys(priv, ctx);
 
1298
                if (ret) {
 
1299
                        IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
 
1300
                        return ret;
 
1301
                }
 
1302
        }
 
1303
        if (new_assoc) {
 
1304
                priv->start_calib = 0;
 
1305
                /* Apply the new configuration
 
1306
                 * RXON assoc doesn't clear the station table in uCode,
 
1307
                 */
 
1308
                ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
 
1309
                              sizeof(struct iwl_legacy_rxon_cmd), &ctx->staging);
 
1310
                if (ret) {
 
1311
                        IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
 
1312
                        return ret;
 
1313
                }
 
1314
                memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
 
1315
        }
 
1316
        iwl_legacy_print_rx_config_cmd(priv, ctx);
 
1317
 
 
1318
        iwl4965_init_sensitivity(priv);
 
1319
 
 
1320
        /* If we issue a new RXON command which required a tune then we must
 
1321
         * send a new TXPOWER command or we won't be able to Tx any frames */
 
1322
        ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true);
 
1323
        if (ret) {
 
1324
                IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
 
1325
                return ret;
 
1326
        }
 
1327
 
 
1328
        return 0;
 
1329
}
 
1330
 
 
1331
static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
 
1332
                                     struct ieee80211_channel_switch *ch_switch)
 
1333
{
 
1334
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
1335
        int rc;
 
1336
        u8 band = 0;
 
1337
        bool is_ht40 = false;
 
1338
        u8 ctrl_chan_high = 0;
 
1339
        struct iwl4965_channel_switch_cmd cmd;
 
1340
        const struct iwl_channel_info *ch_info;
 
1341
        u32 switch_time_in_usec, ucode_switch_time;
 
1342
        u16 ch;
 
1343
        u32 tsf_low;
 
1344
        u8 switch_count;
 
1345
        u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
 
1346
        struct ieee80211_vif *vif = ctx->vif;
 
1347
        band = priv->band == IEEE80211_BAND_2GHZ;
 
1348
 
 
1349
        is_ht40 = iw4965_is_ht40_channel(ctx->staging.flags);
 
1350
 
 
1351
        if (is_ht40 &&
 
1352
            (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
 
1353
                ctrl_chan_high = 1;
 
1354
 
 
1355
        cmd.band = band;
 
1356
        cmd.expect_beacon = 0;
 
1357
        ch = ch_switch->channel->hw_value;
 
1358
        cmd.channel = cpu_to_le16(ch);
 
1359
        cmd.rxon_flags = ctx->staging.flags;
 
1360
        cmd.rxon_filter_flags = ctx->staging.filter_flags;
 
1361
        switch_count = ch_switch->count;
 
1362
        tsf_low = ch_switch->timestamp & 0x0ffffffff;
 
1363
        /*
 
1364
         * calculate the ucode channel switch time
 
1365
         * adding TSF as one of the factor for when to switch
 
1366
         */
 
1367
        if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
 
1368
                if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
 
1369
                    beacon_interval)) {
 
1370
                        switch_count -= (priv->ucode_beacon_time -
 
1371
                                tsf_low) / beacon_interval;
 
1372
                } else
 
1373
                        switch_count = 0;
 
1374
        }
 
1375
        if (switch_count <= 1)
 
1376
                cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
 
1377
        else {
 
1378
                switch_time_in_usec =
 
1379
                        vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
 
1380
                ucode_switch_time = iwl_legacy_usecs_to_beacons(priv,
 
1381
                                                         switch_time_in_usec,
 
1382
                                                         beacon_interval);
 
1383
                cmd.switch_time = iwl_legacy_add_beacon_time(priv,
 
1384
                                                      priv->ucode_beacon_time,
 
1385
                                                      ucode_switch_time,
 
1386
                                                      beacon_interval);
 
1387
        }
 
1388
        IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
 
1389
                      cmd.switch_time);
 
1390
        ch_info = iwl_legacy_get_channel_info(priv, priv->band, ch);
 
1391
        if (ch_info)
 
1392
                cmd.expect_beacon = iwl_legacy_is_channel_radar(ch_info);
 
1393
        else {
 
1394
                IWL_ERR(priv, "invalid channel switch from %u to %u\n",
 
1395
                        ctx->active.channel, ch);
 
1396
                return -EFAULT;
 
1397
        }
 
1398
 
 
1399
        rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
 
1400
                                      ctrl_chan_high, &cmd.tx_power);
 
1401
        if (rc) {
 
1402
                IWL_DEBUG_11H(priv, "error:%d  fill txpower_tbl\n", rc);
 
1403
                return rc;
 
1404
        }
 
1405
 
 
1406
        priv->switch_rxon.channel = cmd.channel;
 
1407
        priv->switch_rxon.switch_in_progress = true;
 
1408
 
 
1409
        return iwl_legacy_send_cmd_pdu(priv,
 
1410
                         REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
 
1411
}
 
1412
 
 
1413
/**
 
1414
 * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
 
1415
 */
 
1416
static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
 
1417
                                            struct iwl_tx_queue *txq,
 
1418
                                            u16 byte_cnt)
 
1419
{
 
1420
        struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
 
1421
        int txq_id = txq->q.id;
 
1422
        int write_ptr = txq->q.write_ptr;
 
1423
        int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
 
1424
        __le16 bc_ent;
 
1425
 
 
1426
        WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
 
1427
 
 
1428
        bc_ent = cpu_to_le16(len & 0xFFF);
 
1429
        /* Set up byte count within first 256 entries */
 
1430
        scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
 
1431
 
 
1432
        /* If within first 64 entries, duplicate at end */
 
1433
        if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
 
1434
                scd_bc_tbl[txq_id].
 
1435
                        tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 
1436
}
 
1437
 
 
1438
/**
 
1439
 * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
 
1440
 * @statistics: Provides the temperature reading from the uCode
 
1441
 *
 
1442
 * A return of <0 indicates bogus data in the statistics
 
1443
 */
 
1444
static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
 
1445
{
 
1446
        s32 temperature;
 
1447
        s32 vt;
 
1448
        s32 R1, R2, R3;
 
1449
        u32 R4;
 
1450
 
 
1451
        if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
 
1452
            (priv->_4965.statistics.flag &
 
1453
                        STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
 
1454
                IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
 
1455
                R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
 
1456
                R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
 
1457
                R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]);
 
1458
                R4 = le32_to_cpu(priv->card_alive_init.therm_r4[1]);
 
1459
        } else {
 
1460
                IWL_DEBUG_TEMP(priv, "Running temperature calibration\n");
 
1461
                R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[0]);
 
1462
                R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[0]);
 
1463
                R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[0]);
 
1464
                R4 = le32_to_cpu(priv->card_alive_init.therm_r4[0]);
 
1465
        }
 
1466
 
 
1467
        /*
 
1468
         * Temperature is only 23 bits, so sign extend out to 32.
 
1469
         *
 
1470
         * NOTE If we haven't received a statistics notification yet
 
1471
         * with an updated temperature, use R4 provided to us in the
 
1472
         * "initialize" ALIVE response.
 
1473
         */
 
1474
        if (!test_bit(STATUS_TEMPERATURE, &priv->status))
 
1475
                vt = sign_extend32(R4, 23);
 
1476
        else
 
1477
                vt = sign_extend32(le32_to_cpu(priv->_4965.statistics.
 
1478
                                 general.common.temperature), 23);
 
1479
 
 
1480
        IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
 
1481
 
 
1482
        if (R3 == R1) {
 
1483
                IWL_ERR(priv, "Calibration conflict R1 == R3\n");
 
1484
                return -1;
 
1485
        }
 
1486
 
 
1487
        /* Calculate temperature in degrees Kelvin, adjust by 97%.
 
1488
         * Add offset to center the adjustment around 0 degrees Centigrade. */
 
1489
        temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2);
 
1490
        temperature /= (R3 - R1);
 
1491
        temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET;
 
1492
 
 
1493
        IWL_DEBUG_TEMP(priv, "Calibrated temperature: %dK, %dC\n",
 
1494
                        temperature, KELVIN_TO_CELSIUS(temperature));
 
1495
 
 
1496
        return temperature;
 
1497
}
 
1498
 
 
1499
/* Adjust Txpower only if temperature variance is greater than threshold. */
 
1500
#define IWL_TEMPERATURE_THRESHOLD   3
 
1501
 
 
1502
/**
 
1503
 * iwl4965_is_temp_calib_needed - determines if new calibration is needed
 
1504
 *
 
1505
 * If the temperature changed has changed sufficiently, then a recalibration
 
1506
 * is needed.
 
1507
 *
 
1508
 * Assumes caller will replace priv->last_temperature once calibration
 
1509
 * executed.
 
1510
 */
 
1511
static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
 
1512
{
 
1513
        int temp_diff;
 
1514
 
 
1515
        if (!test_bit(STATUS_STATISTICS, &priv->status)) {
 
1516
                IWL_DEBUG_TEMP(priv, "Temperature not updated -- no statistics.\n");
 
1517
                return 0;
 
1518
        }
 
1519
 
 
1520
        temp_diff = priv->temperature - priv->last_temperature;
 
1521
 
 
1522
        /* get absolute value */
 
1523
        if (temp_diff < 0) {
 
1524
                IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff);
 
1525
                temp_diff = -temp_diff;
 
1526
        } else if (temp_diff == 0)
 
1527
                IWL_DEBUG_POWER(priv, "Temperature unchanged\n");
 
1528
        else
 
1529
                IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff);
 
1530
 
 
1531
        if (temp_diff < IWL_TEMPERATURE_THRESHOLD) {
 
1532
                IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n");
 
1533
                return 0;
 
1534
        }
 
1535
 
 
1536
        IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n");
 
1537
 
 
1538
        return 1;
 
1539
}
 
1540
 
 
1541
static void iwl4965_temperature_calib(struct iwl_priv *priv)
 
1542
{
 
1543
        s32 temp;
 
1544
 
 
1545
        temp = iwl4965_hw_get_temperature(priv);
 
1546
        if (temp < 0)
 
1547
                return;
 
1548
 
 
1549
        if (priv->temperature != temp) {
 
1550
                if (priv->temperature)
 
1551
                        IWL_DEBUG_TEMP(priv, "Temperature changed "
 
1552
                                       "from %dC to %dC\n",
 
1553
                                       KELVIN_TO_CELSIUS(priv->temperature),
 
1554
                                       KELVIN_TO_CELSIUS(temp));
 
1555
                else
 
1556
                        IWL_DEBUG_TEMP(priv, "Temperature "
 
1557
                                       "initialized to %dC\n",
 
1558
                                       KELVIN_TO_CELSIUS(temp));
 
1559
        }
 
1560
 
 
1561
        priv->temperature = temp;
 
1562
        set_bit(STATUS_TEMPERATURE, &priv->status);
 
1563
 
 
1564
        if (!priv->disable_tx_power_cal &&
 
1565
             unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
 
1566
             iwl4965_is_temp_calib_needed(priv))
 
1567
                queue_work(priv->workqueue, &priv->txpower_work);
 
1568
}
 
1569
 
 
1570
static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len)
 
1571
{
 
1572
        switch (cmd_id) {
 
1573
        case REPLY_RXON:
 
1574
                return (u16) sizeof(struct iwl4965_rxon_cmd);
 
1575
        default:
 
1576
                return len;
 
1577
        }
 
1578
}
 
1579
 
 
1580
static u16 iwl4965_build_addsta_hcmd(const struct iwl_legacy_addsta_cmd *cmd,
 
1581
                                                                u8 *data)
 
1582
{
 
1583
        struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data;
 
1584
        addsta->mode = cmd->mode;
 
1585
        memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
 
1586
        memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
 
1587
        addsta->station_flags = cmd->station_flags;
 
1588
        addsta->station_flags_msk = cmd->station_flags_msk;
 
1589
        addsta->tid_disable_tx = cmd->tid_disable_tx;
 
1590
        addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
 
1591
        addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
 
1592
        addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
 
1593
        addsta->sleep_tx_count = cmd->sleep_tx_count;
 
1594
        addsta->reserved1 = cpu_to_le16(0);
 
1595
        addsta->reserved2 = cpu_to_le16(0);
 
1596
 
 
1597
        return (u16)sizeof(struct iwl4965_addsta_cmd);
 
1598
}
 
1599
 
 
1600
static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
 
1601
{
 
1602
        return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN;
 
1603
}
 
1604
 
 
1605
/**
 
1606
 * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
 
1607
 */
 
1608
static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
 
1609
                                      struct iwl_ht_agg *agg,
 
1610
                                      struct iwl4965_tx_resp *tx_resp,
 
1611
                                      int txq_id, u16 start_idx)
 
1612
{
 
1613
        u16 status;
 
1614
        struct agg_tx_status *frame_status = tx_resp->u.agg_status;
 
1615
        struct ieee80211_tx_info *info = NULL;
 
1616
        struct ieee80211_hdr *hdr = NULL;
 
1617
        u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
 
1618
        int i, sh, idx;
 
1619
        u16 seq;
 
1620
        if (agg->wait_for_ba)
 
1621
                IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
 
1622
 
 
1623
        agg->frame_count = tx_resp->frame_count;
 
1624
        agg->start_idx = start_idx;
 
1625
        agg->rate_n_flags = rate_n_flags;
 
1626
        agg->bitmap = 0;
 
1627
 
 
1628
        /* num frames attempted by Tx command */
 
1629
        if (agg->frame_count == 1) {
 
1630
                /* Only one frame was attempted; no block-ack will arrive */
 
1631
                status = le16_to_cpu(frame_status[0].status);
 
1632
                idx = start_idx;
 
1633
 
 
1634
                IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
 
1635
                                   agg->frame_count, agg->start_idx, idx);
 
1636
 
 
1637
                info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
 
1638
                info->status.rates[0].count = tx_resp->failure_frame + 1;
 
1639
                info->flags &= ~IEEE80211_TX_CTL_AMPDU;
 
1640
                info->flags |= iwl4965_tx_status_to_mac80211(status);
 
1641
                iwl4965_hwrate_to_tx_control(priv, rate_n_flags, info);
 
1642
 
 
1643
                IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
 
1644
                                    status & 0xff, tx_resp->failure_frame);
 
1645
                IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
 
1646
 
 
1647
                agg->wait_for_ba = 0;
 
1648
        } else {
 
1649
                /* Two or more frames were attempted; expect block-ack */
 
1650
                u64 bitmap = 0;
 
1651
                int start = agg->start_idx;
 
1652
 
 
1653
                /* Construct bit-map of pending frames within Tx window */
 
1654
                for (i = 0; i < agg->frame_count; i++) {
 
1655
                        u16 sc;
 
1656
                        status = le16_to_cpu(frame_status[i].status);
 
1657
                        seq  = le16_to_cpu(frame_status[i].sequence);
 
1658
                        idx = SEQ_TO_INDEX(seq);
 
1659
                        txq_id = SEQ_TO_QUEUE(seq);
 
1660
 
 
1661
                        if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
 
1662
                                      AGG_TX_STATE_ABORT_MSK))
 
1663
                                continue;
 
1664
 
 
1665
                        IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
 
1666
                                           agg->frame_count, txq_id, idx);
 
1667
 
 
1668
                        hdr = iwl_legacy_tx_queue_get_hdr(priv, txq_id, idx);
 
1669
                        if (!hdr) {
 
1670
                                IWL_ERR(priv,
 
1671
                                        "BUG_ON idx doesn't point to valid skb"
 
1672
                                        " idx=%d, txq_id=%d\n", idx, txq_id);
 
1673
                                return -1;
 
1674
                        }
 
1675
 
 
1676
                        sc = le16_to_cpu(hdr->seq_ctrl);
 
1677
                        if (idx != (SEQ_TO_SN(sc) & 0xff)) {
 
1678
                                IWL_ERR(priv,
 
1679
                                        "BUG_ON idx doesn't match seq control"
 
1680
                                        " idx=%d, seq_idx=%d, seq=%d\n",
 
1681
                                        idx, SEQ_TO_SN(sc), hdr->seq_ctrl);
 
1682
                                return -1;
 
1683
                        }
 
1684
 
 
1685
                        IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
 
1686
                                           i, idx, SEQ_TO_SN(sc));
 
1687
 
 
1688
                        sh = idx - start;
 
1689
                        if (sh > 64) {
 
1690
                                sh = (start - idx) + 0xff;
 
1691
                                bitmap = bitmap << sh;
 
1692
                                sh = 0;
 
1693
                                start = idx;
 
1694
                        } else if (sh < -64)
 
1695
                                sh  = 0xff - (start - idx);
 
1696
                        else if (sh < 0) {
 
1697
                                sh = start - idx;
 
1698
                                start = idx;
 
1699
                                bitmap = bitmap << sh;
 
1700
                                sh = 0;
 
1701
                        }
 
1702
                        bitmap |= 1ULL << sh;
 
1703
                        IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
 
1704
                                           start, (unsigned long long)bitmap);
 
1705
                }
 
1706
 
 
1707
                agg->bitmap = bitmap;
 
1708
                agg->start_idx = start;
 
1709
                IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
 
1710
                                   agg->frame_count, agg->start_idx,
 
1711
                                   (unsigned long long)agg->bitmap);
 
1712
 
 
1713
                if (bitmap)
 
1714
                        agg->wait_for_ba = 1;
 
1715
        }
 
1716
        return 0;
 
1717
}
 
1718
 
 
1719
static u8 iwl4965_find_station(struct iwl_priv *priv, const u8 *addr)
 
1720
{
 
1721
        int i;
 
1722
        int start = 0;
 
1723
        int ret = IWL_INVALID_STATION;
 
1724
        unsigned long flags;
 
1725
 
 
1726
        if ((priv->iw_mode == NL80211_IFTYPE_ADHOC))
 
1727
                start = IWL_STA_ID;
 
1728
 
 
1729
        if (is_broadcast_ether_addr(addr))
 
1730
                return priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
 
1731
 
 
1732
        spin_lock_irqsave(&priv->sta_lock, flags);
 
1733
        for (i = start; i < priv->hw_params.max_stations; i++)
 
1734
                if (priv->stations[i].used &&
 
1735
                    (!compare_ether_addr(priv->stations[i].sta.sta.addr,
 
1736
                                         addr))) {
 
1737
                        ret = i;
 
1738
                        goto out;
 
1739
                }
 
1740
 
 
1741
        IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n",
 
1742
                              addr, priv->num_stations);
 
1743
 
 
1744
 out:
 
1745
        /*
 
1746
         * It may be possible that more commands interacting with stations
 
1747
         * arrive before we completed processing the adding of
 
1748
         * station
 
1749
         */
 
1750
        if (ret != IWL_INVALID_STATION &&
 
1751
            (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) ||
 
1752
             ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) &&
 
1753
              (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) {
 
1754
                IWL_ERR(priv, "Requested station info for sta %d before ready.\n",
 
1755
                        ret);
 
1756
                ret = IWL_INVALID_STATION;
 
1757
        }
 
1758
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
1759
        return ret;
 
1760
}
 
1761
 
 
1762
static int iwl4965_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
 
1763
{
 
1764
        if (priv->iw_mode == NL80211_IFTYPE_STATION) {
 
1765
                return IWL_AP_ID;
 
1766
        } else {
 
1767
                u8 *da = ieee80211_get_DA(hdr);
 
1768
                return iwl4965_find_station(priv, da);
 
1769
        }
 
1770
}
 
1771
 
 
1772
/**
 
1773
 * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
 
1774
 */
 
1775
static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
 
1776
                                struct iwl_rx_mem_buffer *rxb)
 
1777
{
 
1778
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
1779
        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
 
1780
        int txq_id = SEQ_TO_QUEUE(sequence);
 
1781
        int index = SEQ_TO_INDEX(sequence);
 
1782
        struct iwl_tx_queue *txq = &priv->txq[txq_id];
 
1783
        struct ieee80211_hdr *hdr;
 
1784
        struct ieee80211_tx_info *info;
 
1785
        struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
 
1786
        u32  status = le32_to_cpu(tx_resp->u.status);
 
1787
        int uninitialized_var(tid);
 
1788
        int sta_id;
 
1789
        int freed;
 
1790
        u8 *qc = NULL;
 
1791
        unsigned long flags;
 
1792
 
 
1793
        if ((index >= txq->q.n_bd) || (iwl_legacy_queue_used(&txq->q, index) == 0)) {
 
1794
                IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
 
1795
                          "is out of range [0-%d] %d %d\n", txq_id,
 
1796
                          index, txq->q.n_bd, txq->q.write_ptr,
 
1797
                          txq->q.read_ptr);
 
1798
                return;
 
1799
        }
 
1800
 
 
1801
        txq->time_stamp = jiffies;
 
1802
        info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
 
1803
        memset(&info->status, 0, sizeof(info->status));
 
1804
 
 
1805
        hdr = iwl_legacy_tx_queue_get_hdr(priv, txq_id, index);
 
1806
        if (ieee80211_is_data_qos(hdr->frame_control)) {
 
1807
                qc = ieee80211_get_qos_ctl(hdr);
 
1808
                tid = qc[0] & 0xf;
 
1809
        }
 
1810
 
 
1811
        sta_id = iwl4965_get_ra_sta_id(priv, hdr);
 
1812
        if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
 
1813
                IWL_ERR(priv, "Station not known\n");
 
1814
                return;
 
1815
        }
 
1816
 
 
1817
        spin_lock_irqsave(&priv->sta_lock, flags);
 
1818
        if (txq->sched_retry) {
 
1819
                const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
 
1820
                struct iwl_ht_agg *agg = NULL;
 
1821
                WARN_ON(!qc);
 
1822
 
 
1823
                agg = &priv->stations[sta_id].tid[tid].agg;
 
1824
 
 
1825
                iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
 
1826
 
 
1827
                /* check if BAR is needed */
 
1828
                if ((tx_resp->frame_count == 1) && !iwl4965_is_tx_success(status))
 
1829
                        info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
 
1830
 
 
1831
                if (txq->q.read_ptr != (scd_ssn & 0xff)) {
 
1832
                        index = iwl_legacy_queue_dec_wrap(scd_ssn & 0xff,
 
1833
                                                                txq->q.n_bd);
 
1834
                        IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
 
1835
                                           "%d index %d\n", scd_ssn , index);
 
1836
                        freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
 
1837
                        if (qc)
 
1838
                                iwl4965_free_tfds_in_queue(priv, sta_id,
 
1839
                                                       tid, freed);
 
1840
 
 
1841
                        if (priv->mac80211_registered &&
 
1842
                            (iwl_legacy_queue_space(&txq->q) > txq->q.low_mark)
 
1843
                                 && (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
 
1844
                                iwl_legacy_wake_queue(priv, txq);
 
1845
                }
 
1846
        } else {
 
1847
                info->status.rates[0].count = tx_resp->failure_frame + 1;
 
1848
                info->flags |= iwl4965_tx_status_to_mac80211(status);
 
1849
                iwl4965_hwrate_to_tx_control(priv,
 
1850
                                        le32_to_cpu(tx_resp->rate_n_flags),
 
1851
                                        info);
 
1852
 
 
1853
                IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) "
 
1854
                                   "rate_n_flags 0x%x retries %d\n",
 
1855
                                   txq_id,
 
1856
                                   iwl4965_get_tx_fail_reason(status), status,
 
1857
                                   le32_to_cpu(tx_resp->rate_n_flags),
 
1858
                                   tx_resp->failure_frame);
 
1859
 
 
1860
                freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
 
1861
                if (qc && likely(sta_id != IWL_INVALID_STATION))
 
1862
                        iwl4965_free_tfds_in_queue(priv, sta_id, tid, freed);
 
1863
                else if (sta_id == IWL_INVALID_STATION)
 
1864
                        IWL_DEBUG_TX_REPLY(priv, "Station not known\n");
 
1865
 
 
1866
                if (priv->mac80211_registered &&
 
1867
                    (iwl_legacy_queue_space(&txq->q) > txq->q.low_mark))
 
1868
                        iwl_legacy_wake_queue(priv, txq);
 
1869
        }
 
1870
        if (qc && likely(sta_id != IWL_INVALID_STATION))
 
1871
                iwl4965_txq_check_empty(priv, sta_id, tid, txq_id);
 
1872
 
 
1873
        iwl4965_check_abort_status(priv, tx_resp->frame_count, status);
 
1874
 
 
1875
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
1876
}
 
1877
 
 
1878
static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
 
1879
                                    struct iwl_rx_mem_buffer *rxb)
 
1880
{
 
1881
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
1882
        struct iwl4965_beacon_notif *beacon = (void *)pkt->u.raw;
 
1883
        u8 rate __maybe_unused =
 
1884
                iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
 
1885
 
 
1886
        IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d "
 
1887
                "tsf:0x%.8x%.8x rate:%d\n",
 
1888
                le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
 
1889
                beacon->beacon_notify_hdr.failure_frame,
 
1890
                le32_to_cpu(beacon->ibss_mgr_status),
 
1891
                le32_to_cpu(beacon->high_tsf),
 
1892
                le32_to_cpu(beacon->low_tsf), rate);
 
1893
 
 
1894
        priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
 
1895
}
 
1896
 
 
1897
/* Set up 4965-specific Rx frame reply handlers */
 
1898
static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
 
1899
{
 
1900
        /* Legacy Rx frames */
 
1901
        priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx;
 
1902
        /* Tx response */
 
1903
        priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
 
1904
        priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
 
1905
}
 
1906
 
 
1907
static struct iwl_hcmd_ops iwl4965_hcmd = {
 
1908
        .rxon_assoc = iwl4965_send_rxon_assoc,
 
1909
        .commit_rxon = iwl4965_commit_rxon,
 
1910
        .set_rxon_chain = iwl4965_set_rxon_chain,
 
1911
};
 
1912
 
 
1913
static void iwl4965_post_scan(struct iwl_priv *priv)
 
1914
{
 
1915
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
1916
 
 
1917
        /*
 
1918
         * Since setting the RXON may have been deferred while
 
1919
         * performing the scan, fire one off if needed
 
1920
         */
 
1921
        if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
 
1922
                iwl_legacy_commit_rxon(priv, ctx);
 
1923
}
 
1924
 
 
1925
static void iwl4965_post_associate(struct iwl_priv *priv)
 
1926
{
 
1927
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
1928
        struct ieee80211_vif *vif = ctx->vif;
 
1929
        struct ieee80211_conf *conf = NULL;
 
1930
        int ret = 0;
 
1931
 
 
1932
        if (!vif || !priv->is_open)
 
1933
                return;
 
1934
 
 
1935
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 
1936
                return;
 
1937
 
 
1938
        iwl_legacy_scan_cancel_timeout(priv, 200);
 
1939
 
 
1940
        conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
 
1941
 
 
1942
        ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 
1943
        iwl_legacy_commit_rxon(priv, ctx);
 
1944
 
 
1945
        ret = iwl_legacy_send_rxon_timing(priv, ctx);
 
1946
        if (ret)
 
1947
                IWL_WARN(priv, "RXON timing - "
 
1948
                            "Attempting to continue.\n");
 
1949
 
 
1950
        ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 
1951
 
 
1952
        iwl_legacy_set_rxon_ht(priv, &priv->current_ht_config);
 
1953
 
 
1954
        if (priv->cfg->ops->hcmd->set_rxon_chain)
 
1955
                priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 
1956
 
 
1957
        ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
 
1958
 
 
1959
        IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
 
1960
                        vif->bss_conf.aid, vif->bss_conf.beacon_int);
 
1961
 
 
1962
        if (vif->bss_conf.use_short_preamble)
 
1963
                ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 
1964
        else
 
1965
                ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
1966
 
 
1967
        if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
 
1968
                if (vif->bss_conf.use_short_slot)
 
1969
                        ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
 
1970
                else
 
1971
                        ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
1972
        }
 
1973
 
 
1974
        iwl_legacy_commit_rxon(priv, ctx);
 
1975
 
 
1976
        IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
 
1977
                        vif->bss_conf.aid, ctx->active.bssid_addr);
 
1978
 
 
1979
        switch (vif->type) {
 
1980
        case NL80211_IFTYPE_STATION:
 
1981
                break;
 
1982
        case NL80211_IFTYPE_ADHOC:
 
1983
                iwl4965_send_beacon_cmd(priv);
 
1984
                break;
 
1985
        default:
 
1986
                IWL_ERR(priv, "%s Should not be called in %d mode\n",
 
1987
                          __func__, vif->type);
 
1988
                break;
 
1989
        }
 
1990
 
 
1991
        /* the chain noise calibration will enabled PM upon completion
 
1992
         * If chain noise has already been run, then we need to enable
 
1993
         * power management here */
 
1994
        if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
 
1995
                iwl_legacy_power_update_mode(priv, false);
 
1996
 
 
1997
        /* Enable Rx differential gain and sensitivity calibrations */
 
1998
        iwl4965_chain_noise_reset(priv);
 
1999
        priv->start_calib = 1;
 
2000
}
 
2001
 
 
2002
static void iwl4965_config_ap(struct iwl_priv *priv)
 
2003
{
 
2004
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
2005
        struct ieee80211_vif *vif = ctx->vif;
 
2006
        int ret = 0;
 
2007
 
 
2008
        lockdep_assert_held(&priv->mutex);
 
2009
 
 
2010
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 
2011
                return;
 
2012
 
 
2013
        /* The following should be done only at AP bring up */
 
2014
        if (!iwl_legacy_is_associated_ctx(ctx)) {
 
2015
 
 
2016
                /* RXON - unassoc (to set timing command) */
 
2017
                ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 
2018
                iwl_legacy_commit_rxon(priv, ctx);
 
2019
 
 
2020
                /* RXON Timing */
 
2021
                ret = iwl_legacy_send_rxon_timing(priv, ctx);
 
2022
                if (ret)
 
2023
                        IWL_WARN(priv, "RXON timing failed - "
 
2024
                                        "Attempting to continue.\n");
 
2025
 
 
2026
                /* AP has all antennas */
 
2027
                priv->chain_noise_data.active_chains =
 
2028
                        priv->hw_params.valid_rx_ant;
 
2029
                iwl_legacy_set_rxon_ht(priv, &priv->current_ht_config);
 
2030
                if (priv->cfg->ops->hcmd->set_rxon_chain)
 
2031
                        priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 
2032
 
 
2033
                ctx->staging.assoc_id = 0;
 
2034
 
 
2035
                if (vif->bss_conf.use_short_preamble)
 
2036
                        ctx->staging.flags |=
 
2037
                                RXON_FLG_SHORT_PREAMBLE_MSK;
 
2038
                else
 
2039
                        ctx->staging.flags &=
 
2040
                                ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
2041
 
 
2042
                if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
 
2043
                        if (vif->bss_conf.use_short_slot)
 
2044
                                ctx->staging.flags |=
 
2045
                                        RXON_FLG_SHORT_SLOT_MSK;
 
2046
                        else
 
2047
                                ctx->staging.flags &=
 
2048
                                        ~RXON_FLG_SHORT_SLOT_MSK;
 
2049
                }
 
2050
                /* need to send beacon cmd before committing assoc RXON! */
 
2051
                iwl4965_send_beacon_cmd(priv);
 
2052
                /* restore RXON assoc */
 
2053
                ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 
2054
                iwl_legacy_commit_rxon(priv, ctx);
 
2055
        }
 
2056
        iwl4965_send_beacon_cmd(priv);
 
2057
}
 
2058
 
 
2059
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
 
2060
        .get_hcmd_size = iwl4965_get_hcmd_size,
 
2061
        .build_addsta_hcmd = iwl4965_build_addsta_hcmd,
 
2062
        .request_scan = iwl4965_request_scan,
 
2063
        .post_scan = iwl4965_post_scan,
 
2064
};
 
2065
 
 
2066
static struct iwl_lib_ops iwl4965_lib = {
 
2067
        .set_hw_params = iwl4965_hw_set_hw_params,
 
2068
        .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
 
2069
        .txq_attach_buf_to_tfd = iwl4965_hw_txq_attach_buf_to_tfd,
 
2070
        .txq_free_tfd = iwl4965_hw_txq_free_tfd,
 
2071
        .txq_init = iwl4965_hw_tx_queue_init,
 
2072
        .rx_handler_setup = iwl4965_rx_handler_setup,
 
2073
        .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
 
2074
        .init_alive_start = iwl4965_init_alive_start,
 
2075
        .load_ucode = iwl4965_load_bsm,
 
2076
        .dump_nic_event_log = iwl4965_dump_nic_event_log,
 
2077
        .dump_nic_error_log = iwl4965_dump_nic_error_log,
 
2078
        .dump_fh = iwl4965_dump_fh,
 
2079
        .set_channel_switch = iwl4965_hw_channel_switch,
 
2080
        .apm_ops = {
 
2081
                .init = iwl_legacy_apm_init,
 
2082
                .config = iwl4965_nic_config,
 
2083
        },
 
2084
        .eeprom_ops = {
 
2085
                .regulatory_bands = {
 
2086
                        EEPROM_REGULATORY_BAND_1_CHANNELS,
 
2087
                        EEPROM_REGULATORY_BAND_2_CHANNELS,
 
2088
                        EEPROM_REGULATORY_BAND_3_CHANNELS,
 
2089
                        EEPROM_REGULATORY_BAND_4_CHANNELS,
 
2090
                        EEPROM_REGULATORY_BAND_5_CHANNELS,
 
2091
                        EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
 
2092
                        EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
 
2093
                },
 
2094
                .acquire_semaphore = iwl4965_eeprom_acquire_semaphore,
 
2095
                .release_semaphore = iwl4965_eeprom_release_semaphore,
 
2096
        },
 
2097
        .send_tx_power  = iwl4965_send_tx_power,
 
2098
        .update_chain_flags = iwl4965_update_chain_flags,
 
2099
        .temp_ops = {
 
2100
                .temperature = iwl4965_temperature_calib,
 
2101
        },
 
2102
        .debugfs_ops = {
 
2103
                .rx_stats_read = iwl4965_ucode_rx_stats_read,
 
2104
                .tx_stats_read = iwl4965_ucode_tx_stats_read,
 
2105
                .general_stats_read = iwl4965_ucode_general_stats_read,
 
2106
        },
 
2107
        .check_plcp_health = iwl4965_good_plcp_health,
 
2108
};
 
2109
 
 
2110
static const struct iwl_legacy_ops iwl4965_legacy_ops = {
 
2111
        .post_associate = iwl4965_post_associate,
 
2112
        .config_ap = iwl4965_config_ap,
 
2113
        .manage_ibss_station = iwl4965_manage_ibss_station,
 
2114
        .update_bcast_stations = iwl4965_update_bcast_stations,
 
2115
};
 
2116
 
 
2117
struct ieee80211_ops iwl4965_hw_ops = {
 
2118
        .tx = iwl4965_mac_tx,
 
2119
        .start = iwl4965_mac_start,
 
2120
        .stop = iwl4965_mac_stop,
 
2121
        .add_interface = iwl_legacy_mac_add_interface,
 
2122
        .remove_interface = iwl_legacy_mac_remove_interface,
 
2123
        .change_interface = iwl_legacy_mac_change_interface,
 
2124
        .config = iwl_legacy_mac_config,
 
2125
        .configure_filter = iwl4965_configure_filter,
 
2126
        .set_key = iwl4965_mac_set_key,
 
2127
        .update_tkip_key = iwl4965_mac_update_tkip_key,
 
2128
        .conf_tx = iwl_legacy_mac_conf_tx,
 
2129
        .reset_tsf = iwl_legacy_mac_reset_tsf,
 
2130
        .bss_info_changed = iwl_legacy_mac_bss_info_changed,
 
2131
        .ampdu_action = iwl4965_mac_ampdu_action,
 
2132
        .hw_scan = iwl_legacy_mac_hw_scan,
 
2133
        .sta_add = iwl4965_mac_sta_add,
 
2134
        .sta_remove = iwl_legacy_mac_sta_remove,
 
2135
        .channel_switch = iwl4965_mac_channel_switch,
 
2136
        .tx_last_beacon = iwl_legacy_mac_tx_last_beacon,
 
2137
};
 
2138
 
 
2139
static const struct iwl_ops iwl4965_ops = {
 
2140
        .lib = &iwl4965_lib,
 
2141
        .hcmd = &iwl4965_hcmd,
 
2142
        .utils = &iwl4965_hcmd_utils,
 
2143
        .led = &iwl4965_led_ops,
 
2144
        .legacy = &iwl4965_legacy_ops,
 
2145
        .ieee80211_ops = &iwl4965_hw_ops,
 
2146
};
 
2147
 
 
2148
static struct iwl_base_params iwl4965_base_params = {
 
2149
        .eeprom_size = IWL4965_EEPROM_IMG_SIZE,
 
2150
        .num_of_queues = IWL49_NUM_QUEUES,
 
2151
        .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
 
2152
        .pll_cfg_val = 0,
 
2153
        .set_l0s = true,
 
2154
        .use_bsm = true,
 
2155
        .led_compensation = 61,
 
2156
        .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
 
2157
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
 
2158
        .wd_timeout = IWL_DEF_WD_TIMEOUT,
 
2159
        .temperature_kelvin = true,
 
2160
        .max_event_log_size = 512,
 
2161
        .ucode_tracing = true,
 
2162
        .sensitivity_calib_by_driver = true,
 
2163
        .chain_noise_calib_by_driver = true,
 
2164
};
 
2165
 
 
2166
struct iwl_cfg iwl4965_cfg = {
 
2167
        .name = "Intel(R) Wireless WiFi Link 4965AGN",
 
2168
        .fw_name_pre = IWL4965_FW_PRE,
 
2169
        .ucode_api_max = IWL4965_UCODE_API_MAX,
 
2170
        .ucode_api_min = IWL4965_UCODE_API_MIN,
 
2171
        .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 
2172
        .valid_tx_ant = ANT_AB,
 
2173
        .valid_rx_ant = ANT_ABC,
 
2174
        .eeprom_ver = EEPROM_4965_EEPROM_VERSION,
 
2175
        .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
 
2176
        .ops = &iwl4965_ops,
 
2177
        .mod_params = &iwl4965_mod_params,
 
2178
        .base_params = &iwl4965_base_params,
 
2179
        .led_mode = IWL_LED_BLINK,
 
2180
        /*
 
2181
         * Force use of chains B and C for scan RX on 5 GHz band
 
2182
         * because the device has off-channel reception on chain A.
 
2183
         */
 
2184
        .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
 
2185
};
 
2186
 
 
2187
/* Module firmware */
 
2188
MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));