1 /******************************************************************************
5 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
24 * Contact Information:
25 * Intel Linux Wireless <ilw@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
28 *****************************************************************************/
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/init.h>
33 #include <linux/sched.h>
39 #include "iwl-trans.h"
41 int iwlagn_send_tx_ant_config(struct iwl_priv
*priv
, u8 valid_tx_ant
)
43 struct iwl_tx_ant_config_cmd tx_ant_cmd
= {
44 .valid
= cpu_to_le32(valid_tx_ant
),
47 if (IWL_UCODE_API(priv
->ucode_ver
) > 1) {
48 IWL_DEBUG_HC(priv
, "select valid tx ant: %u\n", valid_tx_ant
);
49 return trans_send_cmd_pdu(priv
,
50 TX_ANT_CONFIGURATION_CMD
,
52 sizeof(struct iwl_tx_ant_config_cmd
),
55 IWL_DEBUG_HC(priv
, "TX_ANT_CONFIGURATION_CMD not supported\n");
60 void iwlagn_gain_computation(struct iwl_priv
*priv
,
61 u32 average_noise
[NUM_RX_CHAINS
],
62 u16 min_average_noise_antenna_i
,
63 u32 min_average_noise
,
68 struct iwl_chain_noise_data
*data
= &priv
->chain_noise_data
;
71 * Find Gain Code for the chains based on "default chain"
73 for (i
= default_chain
+ 1; i
< NUM_RX_CHAINS
; i
++) {
74 if ((data
->disconn_array
[i
])) {
75 data
->delta_gain_code
[i
] = 0;
79 delta_g
= (priv
->cfg
->base_params
->chain_noise_scale
*
80 ((s32
)average_noise
[default_chain
] -
81 (s32
)average_noise
[i
])) / 1500;
83 /* bound gain by 2 bits value max, 3rd bit is sign */
84 data
->delta_gain_code
[i
] =
85 min(abs(delta_g
), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE
);
89 * set negative sign ...
90 * note to Intel developers: This is uCode API format,
91 * not the format of any internal device registers.
92 * Do not change this format for e.g. 6050 or similar
93 * devices. Change format only if more resolution
94 * (i.e. more than 2 bits magnitude) is needed.
96 data
->delta_gain_code
[i
] |= (1 << 2);
99 IWL_DEBUG_CALIB(priv
, "Delta gains: ANT_B = %d ANT_C = %d\n",
100 data
->delta_gain_code
[1], data
->delta_gain_code
[2]);
102 if (!data
->radio_write
) {
103 struct iwl_calib_chain_noise_gain_cmd cmd
;
105 memset(&cmd
, 0, sizeof(cmd
));
107 iwl_set_calib_hdr(&cmd
.hdr
,
108 priv
->_agn
.phy_calib_chain_noise_gain_cmd
);
109 cmd
.delta_gain_1
= data
->delta_gain_code
[1];
110 cmd
.delta_gain_2
= data
->delta_gain_code
[2];
111 trans_send_cmd_pdu(priv
, REPLY_PHY_CALIBRATION_CMD
,
112 CMD_ASYNC
, sizeof(cmd
), &cmd
);
114 data
->radio_write
= 1;
115 data
->state
= IWL_CHAIN_NOISE_CALIBRATED
;
119 int iwlagn_set_pan_params(struct iwl_priv
*priv
)
121 struct iwl_wipan_params_cmd cmd
;
122 struct iwl_rxon_context
*ctx_bss
, *ctx_pan
;
123 int slot0
= 300, slot1
= 0;
126 if (priv
->valid_contexts
== BIT(IWL_RXON_CTX_BSS
))
129 BUILD_BUG_ON(NUM_IWL_RXON_CTX
!= 2);
131 lockdep_assert_held(&priv
->mutex
);
133 ctx_bss
= &priv
->contexts
[IWL_RXON_CTX_BSS
];
134 ctx_pan
= &priv
->contexts
[IWL_RXON_CTX_PAN
];
137 * If the PAN context is inactive, then we don't need
138 * to update the PAN parameters, the last thing we'll
139 * have done before it goes inactive is making the PAN
140 * parameters be WLAN-only.
142 if (!ctx_pan
->is_active
)
145 memset(&cmd
, 0, sizeof(cmd
));
147 /* only 2 slots are currently allowed */
150 cmd
.slots
[0].type
= 0; /* BSS */
151 cmd
.slots
[1].type
= 1; /* PAN */
153 if (priv
->_agn
.hw_roc_channel
) {
154 /* both contexts must be used for this to happen */
155 slot1
= priv
->_agn
.hw_roc_duration
;
156 slot0
= IWL_MIN_SLOT_TIME
;
157 } else if (ctx_bss
->vif
&& ctx_pan
->vif
) {
158 int bcnint
= ctx_pan
->vif
->bss_conf
.beacon_int
;
159 int dtim
= ctx_pan
->vif
->bss_conf
.dtim_period
?: 1;
161 /* should be set, but seems unused?? */
162 cmd
.flags
|= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE
);
164 if (ctx_pan
->vif
->type
== NL80211_IFTYPE_AP
&&
166 bcnint
!= ctx_bss
->vif
->bss_conf
.beacon_int
) {
168 "beacon intervals don't match (%d, %d)\n",
169 ctx_bss
->vif
->bss_conf
.beacon_int
,
170 ctx_pan
->vif
->bss_conf
.beacon_int
);
172 bcnint
= max_t(int, bcnint
,
173 ctx_bss
->vif
->bss_conf
.beacon_int
);
175 bcnint
= DEFAULT_BEACON_INTERVAL
;
177 slot1
= bcnint
- slot0
;
179 if (test_bit(STATUS_SCAN_HW
, &priv
->status
) ||
180 (!ctx_bss
->vif
->bss_conf
.idle
&&
181 !ctx_bss
->vif
->bss_conf
.assoc
)) {
182 slot0
= dtim
* bcnint
* 3 - IWL_MIN_SLOT_TIME
;
183 slot1
= IWL_MIN_SLOT_TIME
;
184 } else if (!ctx_pan
->vif
->bss_conf
.idle
&&
185 !ctx_pan
->vif
->bss_conf
.assoc
) {
186 slot1
= bcnint
* 3 - IWL_MIN_SLOT_TIME
;
187 slot0
= IWL_MIN_SLOT_TIME
;
189 } else if (ctx_pan
->vif
) {
191 slot1
= max_t(int, 1, ctx_pan
->vif
->bss_conf
.dtim_period
) *
192 ctx_pan
->vif
->bss_conf
.beacon_int
;
193 slot1
= max_t(int, DEFAULT_BEACON_INTERVAL
, slot1
);
195 if (test_bit(STATUS_SCAN_HW
, &priv
->status
)) {
196 slot0
= slot1
* 3 - IWL_MIN_SLOT_TIME
;
197 slot1
= IWL_MIN_SLOT_TIME
;
201 cmd
.slots
[0].width
= cpu_to_le16(slot0
);
202 cmd
.slots
[1].width
= cpu_to_le16(slot1
);
204 ret
= trans_send_cmd_pdu(priv
, REPLY_WIPAN_PARAMS
, CMD_SYNC
,
207 IWL_ERR(priv
, "Error setting PAN parameters (%d)\n", ret
);