aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-05-16 14:21:02 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-16 14:21:02 -0400
commitf51f87a09119a495527a3f15d76db38b8e24beb8 (patch)
treed592b3dd3e9a70615f6481e78ab0099c4dbef116 /drivers
parent3b8ab88acaceb505aa06ef3bbf3a73b92470ae78 (diff)
parent6dc0c7fc7cc0f5ec3d92a3076dfe45028540e526 (diff)
Merge branch 'wireless-next-2.6' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-2000.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c86
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c250
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h66
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-devtrace.h58
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sv-open.c177
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.h34
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c359
24 files changed, 716 insertions, 473 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index b4c81931e136..61d4a11f566b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -171,10 +171,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
171 171
172static struct iwl_lib_ops iwl1000_lib = { 172static struct iwl_lib_ops iwl1000_lib = {
173 .set_hw_params = iwl1000_hw_set_hw_params, 173 .set_hw_params = iwl1000_hw_set_hw_params,
174 .txq_set_sched = iwlagn_txq_set_sched,
175 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
176 .txq_free_tfd = iwl_hw_txq_free_tfd,
177 .txq_init = iwl_hw_tx_queue_init,
178 .rx_handler_setup = iwlagn_rx_handler_setup, 174 .rx_handler_setup = iwlagn_rx_handler_setup,
179 .setup_deferred_work = iwlagn_setup_deferred_work, 175 .setup_deferred_work = iwlagn_setup_deferred_work,
180 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, 176 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index 89b8da7a6c8b..86feec86d130 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -195,9 +195,9 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv,
195 struct ieee80211_vif *vif = ctx->vif; 195 struct ieee80211_vif *vif = ctx->vif;
196 struct iwl_host_cmd hcmd = { 196 struct iwl_host_cmd hcmd = {
197 .id = REPLY_CHANNEL_SWITCH, 197 .id = REPLY_CHANNEL_SWITCH,
198 .len = sizeof(cmd), 198 .len = { sizeof(cmd), },
199 .flags = CMD_SYNC, 199 .flags = CMD_SYNC,
200 .data = &cmd, 200 .data = { &cmd, },
201 }; 201 };
202 202
203 cmd.band = priv->band == IEEE80211_BAND_2GHZ; 203 cmd.band = priv->band == IEEE80211_BAND_2GHZ;
@@ -252,10 +252,6 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv,
252 252
253static struct iwl_lib_ops iwl2000_lib = { 253static struct iwl_lib_ops iwl2000_lib = {
254 .set_hw_params = iwl2000_hw_set_hw_params, 254 .set_hw_params = iwl2000_hw_set_hw_params,
255 .txq_set_sched = iwlagn_txq_set_sched,
256 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
257 .txq_free_tfd = iwl_hw_txq_free_tfd,
258 .txq_init = iwl_hw_tx_queue_init,
259 .rx_handler_setup = iwlagn_rx_handler_setup, 255 .rx_handler_setup = iwlagn_rx_handler_setup,
260 .setup_deferred_work = iwlagn_bt_setup_deferred_work, 256 .setup_deferred_work = iwlagn_bt_setup_deferred_work,
261 .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, 257 .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 98f81df166e3..a70b8cfafda1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -282,9 +282,9 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
282 struct ieee80211_vif *vif = ctx->vif; 282 struct ieee80211_vif *vif = ctx->vif;
283 struct iwl_host_cmd hcmd = { 283 struct iwl_host_cmd hcmd = {
284 .id = REPLY_CHANNEL_SWITCH, 284 .id = REPLY_CHANNEL_SWITCH,
285 .len = sizeof(cmd), 285 .len = { sizeof(cmd), },
286 .flags = CMD_SYNC, 286 .flags = CMD_SYNC,
287 .data = &cmd, 287 .data = { &cmd, },
288 }; 288 };
289 289
290 cmd.band = priv->band == IEEE80211_BAND_2GHZ; 290 cmd.band = priv->band == IEEE80211_BAND_2GHZ;
@@ -339,10 +339,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
339 339
340static struct iwl_lib_ops iwl5000_lib = { 340static struct iwl_lib_ops iwl5000_lib = {
341 .set_hw_params = iwl5000_hw_set_hw_params, 341 .set_hw_params = iwl5000_hw_set_hw_params,
342 .txq_set_sched = iwlagn_txq_set_sched,
343 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
344 .txq_free_tfd = iwl_hw_txq_free_tfd,
345 .txq_init = iwl_hw_tx_queue_init,
346 .rx_handler_setup = iwlagn_rx_handler_setup, 342 .rx_handler_setup = iwlagn_rx_handler_setup,
347 .setup_deferred_work = iwlagn_setup_deferred_work, 343 .setup_deferred_work = iwlagn_setup_deferred_work,
348 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, 344 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
@@ -374,10 +370,6 @@ static struct iwl_lib_ops iwl5000_lib = {
374 370
375static struct iwl_lib_ops iwl5150_lib = { 371static struct iwl_lib_ops iwl5150_lib = {
376 .set_hw_params = iwl5150_hw_set_hw_params, 372 .set_hw_params = iwl5150_hw_set_hw_params,
377 .txq_set_sched = iwlagn_txq_set_sched,
378 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
379 .txq_free_tfd = iwl_hw_txq_free_tfd,
380 .txq_init = iwl_hw_tx_queue_init,
381 .rx_handler_setup = iwlagn_rx_handler_setup, 373 .rx_handler_setup = iwlagn_rx_handler_setup,
382 .setup_deferred_work = iwlagn_setup_deferred_work, 374 .setup_deferred_work = iwlagn_setup_deferred_work,
383 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, 375 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index a7921f9a03c6..f8c710db6e6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -221,9 +221,9 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
221 struct ieee80211_vif *vif = ctx->vif; 221 struct ieee80211_vif *vif = ctx->vif;
222 struct iwl_host_cmd hcmd = { 222 struct iwl_host_cmd hcmd = {
223 .id = REPLY_CHANNEL_SWITCH, 223 .id = REPLY_CHANNEL_SWITCH,
224 .len = sizeof(cmd), 224 .len = { sizeof(cmd), },
225 .flags = CMD_SYNC, 225 .flags = CMD_SYNC,
226 .data = &cmd, 226 .data = { &cmd, },
227 }; 227 };
228 228
229 cmd.band = priv->band == IEEE80211_BAND_2GHZ; 229 cmd.band = priv->band == IEEE80211_BAND_2GHZ;
@@ -278,10 +278,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
278 278
279static struct iwl_lib_ops iwl6000_lib = { 279static struct iwl_lib_ops iwl6000_lib = {
280 .set_hw_params = iwl6000_hw_set_hw_params, 280 .set_hw_params = iwl6000_hw_set_hw_params,
281 .txq_set_sched = iwlagn_txq_set_sched,
282 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
283 .txq_free_tfd = iwl_hw_txq_free_tfd,
284 .txq_init = iwl_hw_tx_queue_init,
285 .rx_handler_setup = iwlagn_rx_handler_setup, 281 .rx_handler_setup = iwlagn_rx_handler_setup,
286 .setup_deferred_work = iwlagn_setup_deferred_work, 282 .setup_deferred_work = iwlagn_setup_deferred_work,
287 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, 283 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
@@ -314,10 +310,6 @@ static struct iwl_lib_ops iwl6000_lib = {
314 310
315static struct iwl_lib_ops iwl6030_lib = { 311static struct iwl_lib_ops iwl6030_lib = {
316 .set_hw_params = iwl6000_hw_set_hw_params, 312 .set_hw_params = iwl6000_hw_set_hw_params,
317 .txq_set_sched = iwlagn_txq_set_sched,
318 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
319 .txq_free_tfd = iwl_hw_txq_free_tfd,
320 .txq_init = iwl_hw_tx_queue_init,
321 .rx_handler_setup = iwlagn_bt_rx_handler_setup, 313 .rx_handler_setup = iwlagn_bt_rx_handler_setup,
322 .setup_deferred_work = iwlagn_bt_setup_deferred_work, 314 .setup_deferred_work = iwlagn_bt_setup_deferred_work,
323 .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, 315 .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index 0f6bb9b2e642..d39efcce8ba7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -87,14 +87,14 @@ int iwl_send_calib_results(struct iwl_priv *priv)
87 87
88 struct iwl_host_cmd hcmd = { 88 struct iwl_host_cmd hcmd = {
89 .id = REPLY_PHY_CALIBRATION_CMD, 89 .id = REPLY_PHY_CALIBRATION_CMD,
90 .flags = CMD_SIZE_HUGE,
91 }; 90 };
92 91
93 for (i = 0; i < IWL_CALIB_MAX; i++) { 92 for (i = 0; i < IWL_CALIB_MAX; i++) {
94 if ((BIT(i) & priv->hw_params.calib_init_cfg) && 93 if ((BIT(i) & priv->hw_params.calib_init_cfg) &&
95 priv->calib_results[i].buf) { 94 priv->calib_results[i].buf) {
96 hcmd.len = priv->calib_results[i].buf_len; 95 hcmd.len[0] = priv->calib_results[i].buf_len;
97 hcmd.data = priv->calib_results[i].buf; 96 hcmd.data[0] = priv->calib_results[i].buf;
97 hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
98 ret = iwl_send_cmd_sync(priv, &hcmd); 98 ret = iwl_send_cmd_sync(priv, &hcmd);
99 if (ret) { 99 if (ret) {
100 IWL_ERR(priv, "Error %d iteration %d\n", 100 IWL_ERR(priv, "Error %d iteration %d\n",
@@ -456,9 +456,9 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
456 struct iwl_sensitivity_data *data = NULL; 456 struct iwl_sensitivity_data *data = NULL;
457 struct iwl_host_cmd cmd_out = { 457 struct iwl_host_cmd cmd_out = {
458 .id = SENSITIVITY_CMD, 458 .id = SENSITIVITY_CMD,
459 .len = sizeof(struct iwl_sensitivity_cmd), 459 .len = { sizeof(struct iwl_sensitivity_cmd), },
460 .flags = CMD_ASYNC, 460 .flags = CMD_ASYNC,
461 .data = &cmd, 461 .data = { &cmd, },
462 }; 462 };
463 463
464 data = &(priv->sensitivity_data); 464 data = &(priv->sensitivity_data);
@@ -491,9 +491,9 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
491 struct iwl_sensitivity_data *data = NULL; 491 struct iwl_sensitivity_data *data = NULL;
492 struct iwl_host_cmd cmd_out = { 492 struct iwl_host_cmd cmd_out = {
493 .id = SENSITIVITY_CMD, 493 .id = SENSITIVITY_CMD,
494 .len = sizeof(struct iwl_enhance_sensitivity_cmd), 494 .len = { sizeof(struct iwl_enhance_sensitivity_cmd), },
495 .flags = CMD_ASYNC, 495 .flags = CMD_ASYNC,
496 .data = &cmd, 496 .data = { &cmd, },
497 }; 497 };
498 498
499 data = &(priv->sensitivity_data); 499 data = &(priv->sensitivity_data);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 8e79653aed9a..f803fb62f8bc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -1140,8 +1140,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
1140{ 1140{
1141 struct iwl_host_cmd cmd = { 1141 struct iwl_host_cmd cmd = {
1142 .id = REPLY_SCAN_CMD, 1142 .id = REPLY_SCAN_CMD,
1143 .len = sizeof(struct iwl_scan_cmd), 1143 .len = { sizeof(struct iwl_scan_cmd), },
1144 .flags = CMD_SIZE_HUGE,
1145 }; 1144 };
1146 struct iwl_scan_cmd *scan; 1145 struct iwl_scan_cmd *scan;
1147 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; 1146 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
@@ -1425,10 +1424,11 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
1425 return -EIO; 1424 return -EIO;
1426 } 1425 }
1427 1426
1428 cmd.len += le16_to_cpu(scan->tx_cmd.len) + 1427 cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) +
1429 scan->channel_count * sizeof(struct iwl_scan_channel); 1428 scan->channel_count * sizeof(struct iwl_scan_channel);
1430 cmd.data = scan; 1429 cmd.data[0] = scan;
1431 scan->len = cpu_to_le16(cmd.len); 1430 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
1431 scan->len = cpu_to_le16(cmd.len[0]);
1432 1432
1433 /* set scan bit here for PAN params */ 1433 /* set scan bit here for PAN params */
1434 set_bit(STATUS_SCAN_HW, &priv->status); 1434 set_bit(STATUS_SCAN_HW, &priv->status);
@@ -1520,9 +1520,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
1520 struct iwl_txfifo_flush_cmd flush_cmd; 1520 struct iwl_txfifo_flush_cmd flush_cmd;
1521 struct iwl_host_cmd cmd = { 1521 struct iwl_host_cmd cmd = {
1522 .id = REPLY_TXFIFO_FLUSH, 1522 .id = REPLY_TXFIFO_FLUSH,
1523 .len = sizeof(struct iwl_txfifo_flush_cmd), 1523 .len = { sizeof(struct iwl_txfifo_flush_cmd), },
1524 .flags = CMD_SYNC, 1524 .flags = CMD_SYNC,
1525 .data = &flush_cmd, 1525 .data = { &flush_cmd, },
1526 }; 1526 };
1527 1527
1528 might_sleep(); 1528 might_sleep();
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 91f26556ac23..fec0df016d68 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -335,6 +335,32 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
335 return tid; 335 return tid;
336} 336}
337 337
338#if defined(CONFIG_MAC80211_DEBUGFS) || defined(CONFIG_IWLWIFI_DEVICE_SVTOOL)
339static void rs_program_fix_rate(struct iwl_priv *priv,
340 struct iwl_lq_sta *lq_sta)
341{
342 struct iwl_station_priv *sta_priv =
343 container_of(lq_sta, struct iwl_station_priv, lq_sta);
344 struct iwl_rxon_context *ctx = sta_priv->common.ctx;
345
346 lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */
347 lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
348 lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
349 lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
350
351 lq_sta->dbg_fixed_rate = priv->dbg_fixed_rate;
352
353 IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
354 lq_sta->lq.sta_id, priv->dbg_fixed_rate);
355
356 if (priv->dbg_fixed_rate) {
357 rs_fill_link_cmd(NULL, lq_sta, priv->dbg_fixed_rate);
358 iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
359 false);
360 }
361}
362#endif
363
338/* 364/*
339 get the traffic load value for tid 365 get the traffic load value for tid
340*/ 366*/
@@ -1046,7 +1072,10 @@ done:
1046 /* See if there's a better rate or modulation mode to try. */ 1072 /* See if there's a better rate or modulation mode to try. */
1047 if (sta && sta->supp_rates[sband->band]) 1073 if (sta && sta->supp_rates[sband->band])
1048 rs_rate_scale_perform(priv, skb, sta, lq_sta); 1074 rs_rate_scale_perform(priv, skb, sta, lq_sta);
1049 1075#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
1076 if (priv->dbg_fixed_rate != lq_sta->dbg_fixed_rate)
1077 rs_program_fix_rate(priv, lq_sta);
1078#endif
1050 if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) 1079 if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
1051 rs_bt_update_lq(priv, ctx, lq_sta); 1080 rs_bt_update_lq(priv, ctx, lq_sta);
1052} 1081}
@@ -2170,11 +2199,11 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
2170 * setup rate table in uCode 2199 * setup rate table in uCode
2171 * return rate_n_flags as used in the table 2200 * return rate_n_flags as used in the table
2172 */ 2201 */
2173static u32 rs_update_rate_tbl(struct iwl_priv *priv, 2202static void rs_update_rate_tbl(struct iwl_priv *priv,
2174 struct iwl_rxon_context *ctx, 2203 struct iwl_rxon_context *ctx,
2175 struct iwl_lq_sta *lq_sta, 2204 struct iwl_lq_sta *lq_sta,
2176 struct iwl_scale_tbl_info *tbl, 2205 struct iwl_scale_tbl_info *tbl,
2177 int index, u8 is_green) 2206 int index, u8 is_green)
2178{ 2207{
2179 u32 rate; 2208 u32 rate;
2180 2209
@@ -2182,8 +2211,6 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv,
2182 rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); 2211 rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
2183 rs_fill_link_cmd(priv, lq_sta, rate); 2212 rs_fill_link_cmd(priv, lq_sta, rate);
2184 iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); 2213 iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
2185
2186 return rate;
2187} 2214}
2188 2215
2189/* 2216/*
@@ -2212,7 +2239,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
2212 u8 update_lq = 0; 2239 u8 update_lq = 0;
2213 struct iwl_scale_tbl_info *tbl, *tbl1; 2240 struct iwl_scale_tbl_info *tbl, *tbl1;
2214 u16 rate_scale_index_msk = 0; 2241 u16 rate_scale_index_msk = 0;
2215 u32 rate;
2216 u8 is_green = 0; 2242 u8 is_green = 0;
2217 u8 active_tbl = 0; 2243 u8 active_tbl = 0;
2218 u8 done_search = 0; 2244 u8 done_search = 0;
@@ -2299,8 +2325,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
2299 tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); 2325 tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
2300 /* get "active" rate info */ 2326 /* get "active" rate info */
2301 index = iwl_hwrate_to_plcp_idx(tbl->current_rate); 2327 index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
2302 rate = rs_update_rate_tbl(priv, ctx, lq_sta, 2328 rs_update_rate_tbl(priv, ctx, lq_sta, tbl,
2303 tbl, index, is_green); 2329 index, is_green);
2304 } 2330 }
2305 return; 2331 return;
2306 } 2332 }
@@ -2541,8 +2567,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
2541lq_update: 2567lq_update:
2542 /* Replace uCode's rate table for the destination station. */ 2568 /* Replace uCode's rate table for the destination station. */
2543 if (update_lq) 2569 if (update_lq)
2544 rate = rs_update_rate_tbl(priv, ctx, lq_sta, 2570 rs_update_rate_tbl(priv, ctx, lq_sta, tbl, index, is_green);
2545 tbl, index, is_green);
2546 2571
2547 if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) { 2572 if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
2548 /* Should we stay with this modulation mode, 2573 /* Should we stay with this modulation mode,
@@ -2871,6 +2896,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
2871 lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; 2896 lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
2872 lq_sta->is_agg = 0; 2897 lq_sta->is_agg = 0;
2873 2898
2899 priv->dbg_fixed_rate = 0;
2874#ifdef CONFIG_MAC80211_DEBUGFS 2900#ifdef CONFIG_MAC80211_DEBUGFS
2875 lq_sta->dbg_fixed_rate = 0; 2901 lq_sta->dbg_fixed_rate = 0;
2876#endif 2902#endif
@@ -3045,7 +3071,6 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
3045 IWL_DEBUG_RATE(priv, "leave\n"); 3071 IWL_DEBUG_RATE(priv, "leave\n");
3046} 3072}
3047 3073
3048
3049#ifdef CONFIG_MAC80211_DEBUGFS 3074#ifdef CONFIG_MAC80211_DEBUGFS
3050static int open_file_generic(struct inode *inode, struct file *file) 3075static int open_file_generic(struct inode *inode, struct file *file)
3051{ 3076{
@@ -3070,6 +3095,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
3070 IWL_DEBUG_RATE(priv, "Fixed rate ON\n"); 3095 IWL_DEBUG_RATE(priv, "Fixed rate ON\n");
3071 } else { 3096 } else {
3072 lq_sta->dbg_fixed_rate = 0; 3097 lq_sta->dbg_fixed_rate = 0;
3098 priv->dbg_fixed_rate = 0;
3073 IWL_ERR(priv, 3099 IWL_ERR(priv,
3074 "Invalid antenna selection 0x%X, Valid is 0x%X\n", 3100 "Invalid antenna selection 0x%X, Valid is 0x%X\n",
3075 ant_sel_tx, valid_tx_ant); 3101 ant_sel_tx, valid_tx_ant);
@@ -3088,9 +3114,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
3088 char buf[64]; 3114 char buf[64];
3089 size_t buf_size; 3115 size_t buf_size;
3090 u32 parsed_rate; 3116 u32 parsed_rate;
3091 struct iwl_station_priv *sta_priv = 3117
3092 container_of(lq_sta, struct iwl_station_priv, lq_sta);
3093 struct iwl_rxon_context *ctx = sta_priv->common.ctx;
3094 3118
3095 priv = lq_sta->drv; 3119 priv = lq_sta->drv;
3096 memset(buf, 0, sizeof(buf)); 3120 memset(buf, 0, sizeof(buf));
@@ -3099,23 +3123,11 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
3099 return -EFAULT; 3123 return -EFAULT;
3100 3124
3101 if (sscanf(buf, "%x", &parsed_rate) == 1) 3125 if (sscanf(buf, "%x", &parsed_rate) == 1)
3102 lq_sta->dbg_fixed_rate = parsed_rate; 3126 priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = parsed_rate;
3103 else 3127 else
3104 lq_sta->dbg_fixed_rate = 0; 3128 priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = 0;
3105
3106 lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */
3107 lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
3108 lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
3109 lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
3110
3111 IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
3112 lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
3113 3129
3114 if (lq_sta->dbg_fixed_rate) { 3130 rs_program_fix_rate(priv, lq_sta);
3115 rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
3116 iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
3117 false);
3118 }
3119 3131
3120 return count; 3132 return count;
3121} 3133}
@@ -3143,7 +3155,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
3143 lq_sta->total_failed, lq_sta->total_success, 3155 lq_sta->total_failed, lq_sta->total_success,
3144 lq_sta->active_legacy_rate); 3156 lq_sta->active_legacy_rate);
3145 desc += sprintf(buff+desc, "fixed rate 0x%X\n", 3157 desc += sprintf(buff+desc, "fixed rate 0x%X\n",
3146 lq_sta->dbg_fixed_rate); 3158 priv->dbg_fixed_rate);
3147 desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", 3159 desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
3148 (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", 3160 (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
3149 (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", 3161 (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
@@ -3254,14 +3266,10 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
3254static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, 3266static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
3255 char __user *user_buf, size_t count, loff_t *ppos) 3267 char __user *user_buf, size_t count, loff_t *ppos)
3256{ 3268{
3257 char buff[120];
3258 int desc = 0;
3259
3260 struct iwl_lq_sta *lq_sta = file->private_data; 3269 struct iwl_lq_sta *lq_sta = file->private_data;
3261 struct iwl_priv *priv;
3262 struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl]; 3270 struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
3263 3271 char buff[120];
3264 priv = lq_sta->drv; 3272 int desc = 0;
3265 3273
3266 if (is_Ht(tbl->lq_type)) 3274 if (is_Ht(tbl->lq_type))
3267 desc += sprintf(buff+desc, 3275 desc += sprintf(buff+desc,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 02387430f7fe..a95ad84c5377 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -289,7 +289,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
289 /* cast away the const for active_rxon in this function */ 289 /* cast away the const for active_rxon in this function */
290 struct iwl_rxon_cmd *active = (void *)&ctx->active; 290 struct iwl_rxon_cmd *active = (void *)&ctx->active;
291 bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); 291 bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
292 bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
293 int ret; 292 int ret;
294 293
295 lockdep_assert_held(&priv->mutex); 294 lockdep_assert_held(&priv->mutex);
@@ -389,11 +388,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
389 * AP station must be done after the BSSID is set to correctly 388 * AP station must be done after the BSSID is set to correctly
390 * set up filters in the device. 389 * set up filters in the device.
391 */ 390 */
392 if ((old_assoc && new_assoc) || !new_assoc) { 391 ret = iwlagn_rxon_disconn(priv, ctx);
393 ret = iwlagn_rxon_disconn(priv, ctx); 392 if (ret)
394 if (ret) 393 return ret;
395 return ret;
396 }
397 394
398 if (new_assoc) 395 if (new_assoc)
399 return iwlagn_rxon_connect(priv, ctx); 396 return iwlagn_rxon_connect(priv, ctx);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 079275f2c64d..0bd722cee5ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -144,7 +144,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
144 size_t cmd_size = sizeof(struct iwl_wep_cmd); 144 size_t cmd_size = sizeof(struct iwl_wep_cmd);
145 struct iwl_host_cmd cmd = { 145 struct iwl_host_cmd cmd = {
146 .id = ctx->wep_key_cmd, 146 .id = ctx->wep_key_cmd,
147 .data = wep_cmd, 147 .data = { wep_cmd, },
148 .flags = CMD_SYNC, 148 .flags = CMD_SYNC,
149 }; 149 };
150 150
@@ -172,7 +172,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
172 172
173 cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX; 173 cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
174 174
175 cmd.len = cmd_size; 175 cmd.len[0] = cmd_size;
176 176
177 if (not_empty || send_if_empty) 177 if (not_empty || send_if_empty)
178 return iwl_send_cmd(priv, &cmd); 178 return iwl_send_cmd(priv, &cmd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 7c1becf9e2c1..9acf0e9d7bda 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -750,12 +750,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
750 spin_unlock(&priv->sta_lock); 750 spin_unlock(&priv->sta_lock);
751 751
752 /* Attach buffers to TFD */ 752 /* Attach buffers to TFD */
753 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, 753 iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1);
754 txcmd_phys, firstlen, 1, 0);
755 if (secondlen > 0) 754 if (secondlen > 0)
756 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, 755 iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
757 phys_addr, secondlen, 756 secondlen, 0);
758 0, 0);
759 757
760 scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + 758 scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
761 offsetof(struct iwl_tx_cmd, scratch); 759 offsetof(struct iwl_tx_cmd, scratch);
@@ -911,7 +909,7 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
911 spin_lock_irqsave(&priv->lock, flags); 909 spin_lock_irqsave(&priv->lock, flags);
912 910
913 /* Turn off all Tx DMA fifos */ 911 /* Turn off all Tx DMA fifos */
914 priv->cfg->ops->lib->txq_set_sched(priv, 0); 912 iwlagn_txq_set_sched(priv, 0);
915 913
916 /* Tell NIC where to find the "keep warm" buffer */ 914 /* Tell NIC where to find the "keep warm" buffer */
917 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); 915 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
@@ -949,7 +947,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
949 spin_lock_irqsave(&priv->lock, flags); 947 spin_lock_irqsave(&priv->lock, flags);
950 948
951 /* Turn off all Tx DMA fifos */ 949 /* Turn off all Tx DMA fifos */
952 priv->cfg->ops->lib->txq_set_sched(priv, 0); 950 iwlagn_txq_set_sched(priv, 0);
953 951
954 /* Tell NIC where to find the "keep warm" buffer */ 952 /* Tell NIC where to find the "keep warm" buffer */
955 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); 953 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
@@ -975,7 +973,7 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
975 /* Turn off all Tx DMA fifos */ 973 /* Turn off all Tx DMA fifos */
976 spin_lock_irqsave(&priv->lock, flags); 974 spin_lock_irqsave(&priv->lock, flags);
977 975
978 priv->cfg->ops->lib->txq_set_sched(priv, 0); 976 iwlagn_txq_set_sched(priv, 0);
979 977
980 /* Stop each Tx DMA channel, and wait for it to be idle */ 978 /* Stop each Tx DMA channel, and wait for it to be idle */
981 for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { 979 for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
@@ -1258,7 +1256,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1258 1256
1259 iwlagn_txq_inval_byte_cnt_tbl(priv, txq); 1257 iwlagn_txq_inval_byte_cnt_tbl(priv, txq);
1260 1258
1261 priv->cfg->ops->lib->txq_free_tfd(priv, txq); 1259 iwlagn_txq_free_tfd(priv, txq);
1262 } 1260 }
1263 return nfreed; 1261 return nfreed;
1264} 1262}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 8bda0e8d6661..97de5d9de67b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -217,8 +217,8 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
217 struct iwl_calib_cfg_cmd calib_cfg_cmd; 217 struct iwl_calib_cfg_cmd calib_cfg_cmd;
218 struct iwl_host_cmd cmd = { 218 struct iwl_host_cmd cmd = {
219 .id = CALIBRATION_CFG_CMD, 219 .id = CALIBRATION_CFG_CMD,
220 .len = sizeof(struct iwl_calib_cfg_cmd), 220 .len = { sizeof(struct iwl_calib_cfg_cmd), },
221 .data = &calib_cfg_cmd, 221 .data = { &calib_cfg_cmd, },
222 }; 222 };
223 223
224 memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); 224 memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
@@ -440,7 +440,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
440 IWL_MASK(0, priv->hw_params.max_txq_num)); 440 IWL_MASK(0, priv->hw_params.max_txq_num));
441 441
442 /* Activate all Tx DMA/FIFO channels */ 442 /* Activate all Tx DMA/FIFO channels */
443 priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); 443 iwlagn_txq_set_sched(priv, IWL_MASK(0, 7));
444 444
445 /* map queues to FIFOs */ 445 /* map queues to FIFOs */
446 if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) 446 if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 3ecc3198d9bf..e027f99f18a5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -134,12 +134,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
134 struct iwl_tx_beacon_cmd *tx_beacon_cmd; 134 struct iwl_tx_beacon_cmd *tx_beacon_cmd;
135 struct iwl_host_cmd cmd = { 135 struct iwl_host_cmd cmd = {
136 .id = REPLY_TX_BEACON, 136 .id = REPLY_TX_BEACON,
137 .flags = CMD_SIZE_HUGE,
138 }; 137 };
139 u32 frame_size; 138 u32 frame_size;
140 u32 rate_flags; 139 u32 rate_flags;
141 u32 rate; 140 u32 rate;
142 int err;
143 141
144 /* 142 /*
145 * We have to set up the TX command, the TX Beacon command, and the 143 * We have to set up the TX command, the TX Beacon command, and the
@@ -156,17 +154,15 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
156 if (WARN_ON(!priv->beacon_skb)) 154 if (WARN_ON(!priv->beacon_skb))
157 return -EINVAL; 155 return -EINVAL;
158 156
159 /* Allocate beacon memory */ 157 /* Allocate beacon command */
160 tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len, 158 if (!priv->beacon_cmd)
161 GFP_KERNEL); 159 priv->beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd), GFP_KERNEL);
160 tx_beacon_cmd = priv->beacon_cmd;
162 if (!tx_beacon_cmd) 161 if (!tx_beacon_cmd)
163 return -ENOMEM; 162 return -ENOMEM;
164 163
165 frame_size = priv->beacon_skb->len; 164 frame_size = priv->beacon_skb->len;
166 165
167 /* Set up TX beacon contents */
168 memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size);
169
170 /* Set up TX command fields */ 166 /* Set up TX command fields */
171 tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); 167 tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
172 tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; 168 tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
@@ -175,7 +171,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
175 TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; 171 TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
176 172
177 /* Set up TX beacon command fields */ 173 /* Set up TX beacon command fields */
178 iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame, 174 iwl_set_beacon_tim(priv, tx_beacon_cmd, priv->beacon_skb->data,
179 frame_size); 175 frame_size);
180 176
181 /* Set up packet rate and flags */ 177 /* Set up packet rate and flags */
@@ -189,164 +185,14 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
189 rate_flags); 185 rate_flags);
190 186
191 /* Submit command */ 187 /* Submit command */
192 cmd.len = sizeof(*tx_beacon_cmd) + frame_size; 188 cmd.len[0] = sizeof(*tx_beacon_cmd);
193 cmd.data = tx_beacon_cmd; 189 cmd.data[0] = tx_beacon_cmd;
194 190 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
195 err = iwl_send_cmd_sync(priv, &cmd); 191 cmd.len[1] = frame_size;
196 192 cmd.data[1] = priv->beacon_skb->data;
197 /* Free temporary storage */ 193 cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
198 kfree(tx_beacon_cmd);
199
200 return err;
201}
202
203static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
204{
205 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
206 194
207 dma_addr_t addr = get_unaligned_le32(&tb->lo); 195 return iwl_send_cmd_sync(priv, &cmd);
208 if (sizeof(dma_addr_t) > sizeof(u32))
209 addr |=
210 ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
211
212 return addr;
213}
214
215static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
216{
217 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
218
219 return le16_to_cpu(tb->hi_n_len) >> 4;
220}
221
222static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
223 dma_addr_t addr, u16 len)
224{
225 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
226 u16 hi_n_len = len << 4;
227
228 put_unaligned_le32(addr, &tb->lo);
229 if (sizeof(dma_addr_t) > sizeof(u32))
230 hi_n_len |= ((addr >> 16) >> 16) & 0xF;
231
232 tb->hi_n_len = cpu_to_le16(hi_n_len);
233
234 tfd->num_tbs = idx + 1;
235}
236
237static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
238{
239 return tfd->num_tbs & 0x1f;
240}
241
242/**
243 * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
244 * @priv - driver private data
245 * @txq - tx queue
246 *
247 * Does NOT advance any TFD circular buffer read/write indexes
248 * Does NOT free the TFD itself (which is within circular buffer)
249 */
250void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
251{
252 struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds;
253 struct iwl_tfd *tfd;
254 struct pci_dev *dev = priv->pci_dev;
255 int index = txq->q.read_ptr;
256 int i;
257 int num_tbs;
258
259 tfd = &tfd_tmp[index];
260
261 /* Sanity check on number of chunks */
262 num_tbs = iwl_tfd_get_num_tbs(tfd);
263
264 if (num_tbs >= IWL_NUM_OF_TBS) {
265 IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
266 /* @todo issue fatal error, it is quite serious situation */
267 return;
268 }
269
270 /* Unmap tx_cmd */
271 if (num_tbs)
272 pci_unmap_single(dev,
273 dma_unmap_addr(&txq->meta[index], mapping),
274 dma_unmap_len(&txq->meta[index], len),
275 PCI_DMA_BIDIRECTIONAL);
276
277 /* Unmap chunks, if any. */
278 for (i = 1; i < num_tbs; i++)
279 pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
280 iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);
281
282 /* free SKB */
283 if (txq->txb) {
284 struct sk_buff *skb;
285
286 skb = txq->txb[txq->q.read_ptr].skb;
287
288 /* can be called from irqs-disabled context */
289 if (skb) {
290 dev_kfree_skb_any(skb);
291 txq->txb[txq->q.read_ptr].skb = NULL;
292 }
293 }
294}
295
296int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
297 struct iwl_tx_queue *txq,
298 dma_addr_t addr, u16 len,
299 u8 reset, u8 pad)
300{
301 struct iwl_queue *q;
302 struct iwl_tfd *tfd, *tfd_tmp;
303 u32 num_tbs;
304
305 q = &txq->q;
306 tfd_tmp = (struct iwl_tfd *)txq->tfds;
307 tfd = &tfd_tmp[q->write_ptr];
308
309 if (reset)
310 memset(tfd, 0, sizeof(*tfd));
311
312 num_tbs = iwl_tfd_get_num_tbs(tfd);
313
314 /* Each TFD can point to a maximum 20 Tx buffers */
315 if (num_tbs >= IWL_NUM_OF_TBS) {
316 IWL_ERR(priv, "Error can not send more than %d chunks\n",
317 IWL_NUM_OF_TBS);
318 return -EINVAL;
319 }
320
321 if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
322 return -EINVAL;
323
324 if (unlikely(addr & ~IWL_TX_DMA_MASK))
325 IWL_ERR(priv, "Unaligned address = %llx\n",
326 (unsigned long long)addr);
327
328 iwl_tfd_set_tb(tfd, num_tbs, addr, len);
329
330 return 0;
331}
332
333/*
334 * Tell nic where to find circular buffer of Tx Frame Descriptors for
335 * given Tx queue, and enable the DMA channel used for that queue.
336 *
337 * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
338 * channels supported in hardware.
339 */
340int iwl_hw_tx_queue_init(struct iwl_priv *priv,
341 struct iwl_tx_queue *txq)
342{
343 int txq_id = txq->q.id;
344
345 /* Circular buffer (TFD queue in DRAM) physical base address */
346 iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
347 txq->q.dma_addr >> 8);
348
349 return 0;
350} 196}
351 197
352static void iwl_bg_beacon_update(struct work_struct *work) 198static void iwl_bg_beacon_update(struct work_struct *work)
@@ -1776,10 +1622,7 @@ static const char *desc_lookup(u32 num)
1776 1622
1777void iwl_dump_nic_error_log(struct iwl_priv *priv) 1623void iwl_dump_nic_error_log(struct iwl_priv *priv)
1778{ 1624{
1779 u32 data2, line; 1625 u32 base;
1780 u32 desc, time, count, base, data1;
1781 u32 blink1, blink2, ilink1, ilink2;
1782 u32 pc, hcmd;
1783 struct iwl_error_event_table table; 1626 struct iwl_error_event_table table;
1784 1627
1785 base = priv->device_pointers.error_event_table; 1628 base = priv->device_pointers.error_event_table;
@@ -1802,37 +1645,40 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
1802 1645
1803 iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); 1646 iwl_read_targ_mem_words(priv, base, &table, sizeof(table));
1804 1647
1805 count = table.valid; 1648 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
1806
1807 if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
1808 IWL_ERR(priv, "Start IWL Error Log Dump:\n"); 1649 IWL_ERR(priv, "Start IWL Error Log Dump:\n");
1809 IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", 1650 IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
1810 priv->status, count); 1651 priv->status, table.valid);
1811 } 1652 }
1812 1653
1813 desc = table.error_id; 1654 priv->isr_stats.err_code = table.error_id;
1814 priv->isr_stats.err_code = desc; 1655
1815 pc = table.pc; 1656 trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
1816 blink1 = table.blink1; 1657 table.data1, table.data2, table.line,
1817 blink2 = table.blink2; 1658 table.blink1, table.blink2, table.ilink1,
1818 ilink1 = table.ilink1; 1659 table.ilink2, table.bcon_time, table.gp1,
1819 ilink2 = table.ilink2; 1660 table.gp2, table.gp3, table.ucode_ver,
1820 data1 = table.data1; 1661 table.hw_ver, table.brd_ver);
1821 data2 = table.data2; 1662 IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id,
1822 line = table.line; 1663 desc_lookup(table.error_id));
1823 time = table.tsf_low; 1664 IWL_ERR(priv, "0x%08X | uPc\n", table.pc);
1824 hcmd = table.hcmd; 1665 IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1);
1825 1666 IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2);
1826 trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, 1667 IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1);
1827 blink1, blink2, ilink1, ilink2); 1668 IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2);
1828 1669 IWL_ERR(priv, "0x%08X | data1\n", table.data1);
1829 IWL_ERR(priv, "Desc Time " 1670 IWL_ERR(priv, "0x%08X | data2\n", table.data2);
1830 "data1 data2 line\n"); 1671 IWL_ERR(priv, "0x%08X | line\n", table.line);
1831 IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n", 1672 IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time);
1832 desc_lookup(desc), desc, time, data1, data2, line); 1673 IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low);
1833 IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); 1674 IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi);
1834 IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", 1675 IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1);
1835 pc, blink1, blink2, ilink1, ilink2, hcmd); 1676 IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2);
1677 IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3);
1678 IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver);
1679 IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver);
1680 IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver);
1681 IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd);
1836} 1682}
1837 1683
1838#define EVENT_START_OFFSET (4 * sizeof(u32)) 1684#define EVENT_START_OFFSET (4 * sizeof(u32))
@@ -2114,8 +1960,8 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
2114 struct iwl_calib_cfg_cmd calib_cfg_cmd; 1960 struct iwl_calib_cfg_cmd calib_cfg_cmd;
2115 struct iwl_host_cmd cmd = { 1961 struct iwl_host_cmd cmd = {
2116 .id = CALIBRATION_CFG_CMD, 1962 .id = CALIBRATION_CFG_CMD,
2117 .len = sizeof(struct iwl_calib_cfg_cmd), 1963 .len = { sizeof(struct iwl_calib_cfg_cmd), },
2118 .data = &calib_cfg_cmd, 1964 .data = { &calib_cfg_cmd, },
2119 }; 1965 };
2120 1966
2121 memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); 1967 memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
@@ -3395,6 +3241,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
3395 iwlcore_free_geos(priv); 3241 iwlcore_free_geos(priv);
3396 iwl_free_channel_map(priv); 3242 iwl_free_channel_map(priv);
3397 kfree(priv->scan_cmd); 3243 kfree(priv->scan_cmd);
3244 kfree(priv->beacon_cmd);
3398} 3245}
3399 3246
3400struct ieee80211_ops iwlagn_hw_ops = { 3247struct ieee80211_ops iwlagn_hw_ops = {
@@ -3812,6 +3659,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
3812 */ 3659 */
3813 set_bit(STATUS_EXIT_PENDING, &priv->status); 3660 set_bit(STATUS_EXIT_PENDING, &priv->status);
3814 3661
3662 iwl_testmode_cleanup(priv);
3815 iwl_leds_exit(priv); 3663 iwl_leds_exit(priv);
3816 3664
3817 if (priv->mac80211_registered) { 3665 if (priv->mac80211_registered) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index fe33fe8aa418..2495fe7a58cb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -191,12 +191,10 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
191void iwl_setup_rx_handlers(struct iwl_priv *priv); 191void iwl_setup_rx_handlers(struct iwl_priv *priv);
192 192
193/* tx */ 193/* tx */
194void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); 194void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
195int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, 195int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
196 struct iwl_tx_queue *txq, 196 struct iwl_tx_queue *txq,
197 dma_addr_t addr, u16 len, u8 reset, u8 pad); 197 dma_addr_t addr, u16 len, u8 reset);
198int iwl_hw_tx_queue_init(struct iwl_priv *priv,
199 struct iwl_tx_queue *txq);
200void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, 198void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
201 struct ieee80211_tx_info *info); 199 struct ieee80211_tx_info *info);
202int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); 200int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
@@ -345,6 +343,7 @@ extern int iwl_alive_start(struct iwl_priv *priv);
345#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL 343#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
346extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); 344extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len);
347extern void iwl_testmode_init(struct iwl_priv *priv); 345extern void iwl_testmode_init(struct iwl_priv *priv);
346extern void iwl_testmode_cleanup(struct iwl_priv *priv);
348#else 347#else
349static inline 348static inline
350int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) 349int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
@@ -355,6 +354,10 @@ static inline
355void iwl_testmode_init(struct iwl_priv *priv) 354void iwl_testmode_init(struct iwl_priv *priv)
356{ 355{
357} 356}
357static inline
358void iwl_testmode_cleanup(struct iwl_priv *priv)
359{
360}
358#endif 361#endif
359 362
360#endif /* __iwl_agn_h__ */ 363#endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 5fdad6532118..6ee5f1aa555c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -205,7 +205,6 @@ enum {
205#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) 205#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
206#define SEQ_TO_INDEX(s) ((s) & 0xff) 206#define SEQ_TO_INDEX(s) ((s) & 0xff)
207#define INDEX_TO_SEQ(i) ((i) & 0xff) 207#define INDEX_TO_SEQ(i) ((i) & 0xff)
208#define SEQ_HUGE_FRAME cpu_to_le16(0x4000)
209#define SEQ_RX_FRAME cpu_to_le16(0x8000) 208#define SEQ_RX_FRAME cpu_to_le16(0x8000)
210 209
211/** 210/**
@@ -234,9 +233,7 @@ struct iwl_cmd_header {
234 * 233 *
235 * 0:7 tfd index - position within TX queue 234 * 0:7 tfd index - position within TX queue
236 * 8:12 TX queue id 235 * 8:12 TX queue id
237 * 13 reserved 236 * 13:14 reserved
238 * 14 huge - driver sets this to indicate command is in the
239 * 'huge' storage at the end of the command buffers
240 * 15 unsolicited RX or uCode-originated notification 237 * 15 unsolicited RX or uCode-originated notification
241 */ 238 */
242 __le16 sequence; 239 __le16 sequence;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 5b5b0cce4a54..3bb76f6ea410 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -127,16 +127,6 @@ struct iwl_temp_ops {
127struct iwl_lib_ops { 127struct iwl_lib_ops {
128 /* set hw dependent parameters */ 128 /* set hw dependent parameters */
129 int (*set_hw_params)(struct iwl_priv *priv); 129 int (*set_hw_params)(struct iwl_priv *priv);
130 /* Handling TX */
131 void (*txq_set_sched)(struct iwl_priv *priv, u32 mask);
132 int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv,
133 struct iwl_tx_queue *txq,
134 dma_addr_t addr,
135 u16 len, u8 reset, u8 pad);
136 void (*txq_free_tfd)(struct iwl_priv *priv,
137 struct iwl_tx_queue *txq);
138 int (*txq_init)(struct iwl_priv *priv,
139 struct iwl_tx_queue *txq);
140 /* setup Rx handler */ 130 /* setup Rx handler */
141 void (*rx_handler_setup)(struct iwl_priv *priv); 131 void (*rx_handler_setup)(struct iwl_priv *priv);
142 /* setup deferred work */ 132 /* setup deferred work */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 214e4658c495..22a6e3ec7094 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -48,8 +48,6 @@
48#include "iwl-agn-rs.h" 48#include "iwl-agn-rs.h"
49#include "iwl-agn-tt.h" 49#include "iwl-agn-tt.h"
50 50
51#define U32_PAD(n) ((4-(n))&0x3)
52
53struct iwl_tx_queue; 51struct iwl_tx_queue;
54 52
55/* CT-KILL constants */ 53/* CT-KILL constants */
@@ -83,7 +81,7 @@ struct iwl_tx_queue;
83#define MAX_RTS_THRESHOLD 2347U 81#define MAX_RTS_THRESHOLD 2347U
84#define MAX_MSDU_SIZE 2304U 82#define MAX_MSDU_SIZE 2304U
85#define MAX_MPDU_SIZE 2346U 83#define MAX_MPDU_SIZE 2346U
86#define DEFAULT_BEACON_INTERVAL 100U 84#define DEFAULT_BEACON_INTERVAL 200U
87#define DEFAULT_SHORT_RETRY_LIMIT 7U 85#define DEFAULT_SHORT_RETRY_LIMIT 7U
88#define DEFAULT_LONG_RETRY_LIMIT 4U 86#define DEFAULT_LONG_RETRY_LIMIT 4U
89 87
@@ -112,8 +110,6 @@ struct iwl_cmd_meta {
112 struct iwl_device_cmd *cmd, 110 struct iwl_device_cmd *cmd,
113 struct iwl_rx_packet *pkt); 111 struct iwl_rx_packet *pkt);
114 112
115 /* The CMD_SIZE_HUGE flag bit indicates that the command
116 * structure is stored at the end of the shared queue memory. */
117 u32 flags; 113 u32 flags;
118 114
119 DEFINE_DMA_UNMAP_ADDR(mapping); 115 DEFINE_DMA_UNMAP_ADDR(mapping);
@@ -123,7 +119,23 @@ struct iwl_cmd_meta {
123/* 119/*
124 * Generic queue structure 120 * Generic queue structure
125 * 121 *
126 * Contains common data for Rx and Tx queues 122 * Contains common data for Rx and Tx queues.
123 *
124 * Note the difference between n_bd and n_window: the hardware
125 * always assumes 256 descriptors, so n_bd is always 256 (unless
126 * there might be HW changes in the future). For the normal TX
127 * queues, n_window, which is the size of the software queue data
128 * is also 256; however, for the command queue, n_window is only
129 * 32 since we don't need so many commands pending. Since the HW
130 * still uses 256 BDs for DMA though, n_bd stays 256. As a result,
131 * the software buffers (in the variables @meta, @txb in struct
132 * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds
133 * in the same struct) have 256.
134 * This means that we end up with the following:
135 * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
136 * SW entries: | 0 | ... | 31 |
137 * where N is a number between 0 and 7. This means that the SW
138 * data is a window overlayed over the HW queue.
127 */ 139 */
128struct iwl_queue { 140struct iwl_queue {
129 int n_bd; /* number of BDs in this queue */ 141 int n_bd; /* number of BDs in this queue */
@@ -165,7 +177,7 @@ struct iwl_tx_info {
165 177
166struct iwl_tx_queue { 178struct iwl_tx_queue {
167 struct iwl_queue q; 179 struct iwl_queue q;
168 void *tfds; 180 struct iwl_tfd *tfds;
169 struct iwl_device_cmd **cmd; 181 struct iwl_device_cmd **cmd;
170 struct iwl_cmd_meta *meta; 182 struct iwl_cmd_meta *meta;
171 struct iwl_tx_info *txb; 183 struct iwl_tx_info *txb;
@@ -247,7 +259,6 @@ enum {
247 CMD_SYNC = 0, 259 CMD_SYNC = 0,
248 CMD_SIZE_NORMAL = 0, 260 CMD_SIZE_NORMAL = 0,
249 CMD_NO_SKB = 0, 261 CMD_NO_SKB = 0,
250 CMD_SIZE_HUGE = (1 << 0),
251 CMD_ASYNC = (1 << 1), 262 CMD_ASYNC = (1 << 1),
252 CMD_WANT_SKB = (1 << 2), 263 CMD_WANT_SKB = (1 << 2),
253 CMD_MAPPED = (1 << 3), 264 CMD_MAPPED = (1 << 3),
@@ -259,8 +270,8 @@ enum {
259 * struct iwl_device_cmd 270 * struct iwl_device_cmd
260 * 271 *
261 * For allocation of the command and tx queues, this establishes the overall 272 * For allocation of the command and tx queues, this establishes the overall
262 * size of the largest command we send to uCode, except for a scan command 273 * size of the largest command we send to uCode, except for commands that
263 * (which is relatively huge; space is allocated separately). 274 * aren't fully copied and use other TFD space.
264 */ 275 */
265struct iwl_device_cmd { 276struct iwl_device_cmd {
266 struct iwl_cmd_header hdr; /* uCode API */ 277 struct iwl_cmd_header hdr; /* uCode API */
@@ -277,15 +288,21 @@ struct iwl_device_cmd {
277 288
278#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) 289#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
279 290
291#define IWL_MAX_CMD_TFDS 2
292
293enum iwl_hcmd_dataflag {
294 IWL_HCMD_DFL_NOCOPY = BIT(0),
295};
280 296
281struct iwl_host_cmd { 297struct iwl_host_cmd {
282 const void *data; 298 const void *data[IWL_MAX_CMD_TFDS];
283 unsigned long reply_page; 299 unsigned long reply_page;
284 void (*callback)(struct iwl_priv *priv, 300 void (*callback)(struct iwl_priv *priv,
285 struct iwl_device_cmd *cmd, 301 struct iwl_device_cmd *cmd,
286 struct iwl_rx_packet *pkt); 302 struct iwl_rx_packet *pkt);
287 u32 flags; 303 u32 flags;
288 u16 len; 304 u16 len[IWL_MAX_CMD_TFDS];
305 u8 dataflags[IWL_MAX_CMD_TFDS];
289 u8 id; 306 u8 id;
290}; 307};
291 308
@@ -688,17 +705,8 @@ static inline int iwl_queue_used(const struct iwl_queue *q, int i)
688} 705}
689 706
690 707
691static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) 708static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
692{ 709{
693 /*
694 * This is for init calibration result and scan command which
695 * required buffer > TFD_MAX_PAYLOAD_SIZE,
696 * the big buffer at end of command array
697 */
698 if (is_huge)
699 return q->n_window; /* must be power of 2 */
700
701 /* Otherwise, use normal size buffers */
702 return index & (q->n_window - 1); 710 return index & (q->n_window - 1);
703} 711}
704 712
@@ -1171,6 +1179,14 @@ enum iwl_scan_type {
1171 IWL_SCAN_OFFCH_TX, 1179 IWL_SCAN_OFFCH_TX,
1172}; 1180};
1173 1181
1182#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
1183struct iwl_testmode_trace {
1184 u8 *cpu_addr;
1185 u8 *trace_addr;
1186 dma_addr_t dma_addr;
1187 bool trace_enabled;
1188};
1189#endif
1174struct iwl_priv { 1190struct iwl_priv {
1175 1191
1176 /* ieee device used by generic ieee processing code */ 1192 /* ieee device used by generic ieee processing code */
@@ -1452,6 +1468,7 @@ struct iwl_priv {
1452 struct work_struct beacon_update; 1468 struct work_struct beacon_update;
1453 struct iwl_rxon_context *beacon_ctx; 1469 struct iwl_rxon_context *beacon_ctx;
1454 struct sk_buff *beacon_skb; 1470 struct sk_buff *beacon_skb;
1471 void *beacon_cmd;
1455 1472
1456 struct work_struct tt_work; 1473 struct work_struct tt_work;
1457 struct work_struct ct_enter; 1474 struct work_struct ct_enter;
@@ -1501,6 +1518,11 @@ struct iwl_priv {
1501 struct led_classdev led; 1518 struct led_classdev led;
1502 unsigned long blink_on, blink_off; 1519 unsigned long blink_on, blink_off;
1503 bool led_registered; 1520 bool led_registered;
1521#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
1522 struct iwl_testmode_trace testmode_trace;
1523#endif
1524 u32 dbg_fixed_rate;
1525
1504}; /*iwl_priv */ 1526}; /*iwl_priv */
1505 1527
1506static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) 1528static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index f00172cb8a6d..2c84ba95afca 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -137,20 +137,27 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
137#define TRACE_SYSTEM iwlwifi 137#define TRACE_SYSTEM iwlwifi
138 138
139TRACE_EVENT(iwlwifi_dev_hcmd, 139TRACE_EVENT(iwlwifi_dev_hcmd,
140 TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags), 140 TP_PROTO(struct iwl_priv *priv, u32 flags,
141 TP_ARGS(priv, hcmd, len, flags), 141 const void *hcmd0, size_t len0,
142 const void *hcmd1, size_t len1,
143 const void *hcmd2, size_t len2),
144 TP_ARGS(priv, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
142 TP_STRUCT__entry( 145 TP_STRUCT__entry(
143 PRIV_ENTRY 146 PRIV_ENTRY
144 __dynamic_array(u8, hcmd, len) 147 __dynamic_array(u8, hcmd0, len0)
148 __dynamic_array(u8, hcmd1, len1)
149 __dynamic_array(u8, hcmd2, len2)
145 __field(u32, flags) 150 __field(u32, flags)
146 ), 151 ),
147 TP_fast_assign( 152 TP_fast_assign(
148 PRIV_ASSIGN; 153 PRIV_ASSIGN;
149 memcpy(__get_dynamic_array(hcmd), hcmd, len); 154 memcpy(__get_dynamic_array(hcmd0), hcmd0, len0);
155 memcpy(__get_dynamic_array(hcmd1), hcmd1, len1);
156 memcpy(__get_dynamic_array(hcmd2), hcmd2, len2);
150 __entry->flags = flags; 157 __entry->flags = flags;
151 ), 158 ),
152 TP_printk("[%p] hcmd %#.2x (%ssync)", 159 TP_printk("[%p] hcmd %#.2x (%ssync)",
153 __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0], 160 __entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0],
154 __entry->flags & CMD_ASYNC ? "a" : "") 161 __entry->flags & CMD_ASYNC ? "a" : "")
155); 162);
156 163
@@ -202,15 +209,18 @@ TRACE_EVENT(iwlwifi_dev_tx,
202); 209);
203 210
204TRACE_EVENT(iwlwifi_dev_ucode_error, 211TRACE_EVENT(iwlwifi_dev_ucode_error,
205 TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time, 212 TP_PROTO(struct iwl_priv *priv, u32 desc, u32 tsf_low,
206 u32 data1, u32 data2, u32 line, u32 blink1, 213 u32 data1, u32 data2, u32 line, u32 blink1,
207 u32 blink2, u32 ilink1, u32 ilink2), 214 u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
208 TP_ARGS(priv, desc, time, data1, data2, line, 215 u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
209 blink1, blink2, ilink1, ilink2), 216 u32 brd_ver),
217 TP_ARGS(priv, desc, tsf_low, data1, data2, line,
218 blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2,
219 gp3, ucode_ver, hw_ver, brd_ver),
210 TP_STRUCT__entry( 220 TP_STRUCT__entry(
211 PRIV_ENTRY 221 PRIV_ENTRY
212 __field(u32, desc) 222 __field(u32, desc)
213 __field(u32, time) 223 __field(u32, tsf_low)
214 __field(u32, data1) 224 __field(u32, data1)
215 __field(u32, data2) 225 __field(u32, data2)
216 __field(u32, line) 226 __field(u32, line)
@@ -218,11 +228,18 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
218 __field(u32, blink2) 228 __field(u32, blink2)
219 __field(u32, ilink1) 229 __field(u32, ilink1)
220 __field(u32, ilink2) 230 __field(u32, ilink2)
231 __field(u32, bcon_time)
232 __field(u32, gp1)
233 __field(u32, gp2)
234 __field(u32, gp3)
235 __field(u32, ucode_ver)
236 __field(u32, hw_ver)
237 __field(u32, brd_ver)
221 ), 238 ),
222 TP_fast_assign( 239 TP_fast_assign(
223 PRIV_ASSIGN; 240 PRIV_ASSIGN;
224 __entry->desc = desc; 241 __entry->desc = desc;
225 __entry->time = time; 242 __entry->tsf_low = tsf_low;
226 __entry->data1 = data1; 243 __entry->data1 = data1;
227 __entry->data2 = data2; 244 __entry->data2 = data2;
228 __entry->line = line; 245 __entry->line = line;
@@ -230,12 +247,25 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
230 __entry->blink2 = blink2; 247 __entry->blink2 = blink2;
231 __entry->ilink1 = ilink1; 248 __entry->ilink1 = ilink1;
232 __entry->ilink2 = ilink2; 249 __entry->ilink2 = ilink2;
250 __entry->bcon_time = bcon_time;
251 __entry->gp1 = gp1;
252 __entry->gp2 = gp2;
253 __entry->gp3 = gp3;
254 __entry->ucode_ver = ucode_ver;
255 __entry->hw_ver = hw_ver;
256 __entry->brd_ver = brd_ver;
233 ), 257 ),
234 TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, " 258 TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, "
235 "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X", 259 "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X "
236 __entry->priv, __entry->desc, __entry->time, __entry->data1, 260 "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X "
261 "hw 0x%08X brd 0x%08X",
262 __entry->priv, __entry->desc, __entry->tsf_low,
263 __entry->data1,
237 __entry->data2, __entry->line, __entry->blink1, 264 __entry->data2, __entry->line, __entry->blink1,
238 __entry->blink2, __entry->ilink1, __entry->ilink2) 265 __entry->blink2, __entry->ilink1, __entry->ilink2,
266 __entry->bcon_time, __entry->gp1, __entry->gp2,
267 __entry->gp3, __entry->ucode_ver, __entry->hw_ver,
268 __entry->brd_ver)
239); 269);
240 270
241TRACE_EVENT(iwlwifi_dev_ucode_event, 271TRACE_EVENT(iwlwifi_dev_ucode_event,
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index c8397962632c..47a56bc1cd12 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -216,15 +216,14 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
216 216
217static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) 217static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
218{ 218{
219 u32 otpgp; 219 iwl_read32(priv, CSR_OTP_GP_REG);
220 220
221 otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
222 if (mode == IWL_OTP_ACCESS_ABSOLUTE) 221 if (mode == IWL_OTP_ACCESS_ABSOLUTE)
223 iwl_clear_bit(priv, CSR_OTP_GP_REG, 222 iwl_clear_bit(priv, CSR_OTP_GP_REG,
224 CSR_OTP_GP_REG_OTP_ACCESS_MODE); 223 CSR_OTP_GP_REG_OTP_ACCESS_MODE);
225 else 224 else
226 iwl_set_bit(priv, CSR_OTP_GP_REG, 225 iwl_set_bit(priv, CSR_OTP_GP_REG,
227 CSR_OTP_GP_REG_OTP_ACCESS_MODE); 226 CSR_OTP_GP_REG_OTP_ACCESS_MODE);
228} 227}
229 228
230static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) 229static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 8f0beb992ccf..76f996623140 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -188,6 +188,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
188 cmd_idx = iwl_enqueue_hcmd(priv, cmd); 188 cmd_idx = iwl_enqueue_hcmd(priv, cmd);
189 if (cmd_idx < 0) { 189 if (cmd_idx < 0) {
190 ret = cmd_idx; 190 ret = cmd_idx;
191 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
191 IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", 192 IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
192 get_cmd_string(cmd->id), ret); 193 get_cmd_string(cmd->id), ret);
193 return ret; 194 return ret;
@@ -264,8 +265,8 @@ int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
264{ 265{
265 struct iwl_host_cmd cmd = { 266 struct iwl_host_cmd cmd = {
266 .id = id, 267 .id = id,
267 .len = len, 268 .len = { len, },
268 .data = data, 269 .data = { data, },
269 }; 270 };
270 271
271 return iwl_send_cmd_sync(priv, &cmd); 272 return iwl_send_cmd_sync(priv, &cmd);
@@ -279,8 +280,8 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
279{ 280{
280 struct iwl_host_cmd cmd = { 281 struct iwl_host_cmd cmd = {
281 .id = id, 282 .id = id,
282 .len = len, 283 .len = { len, },
283 .data = data, 284 .data = { data, },
284 }; 285 };
285 286
286 cmd.flags |= CMD_ASYNC; 287 cmd.flags |= CMD_ASYNC;
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 439187f903c9..7c23beb49d7c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -107,8 +107,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
107{ 107{
108 struct iwl_host_cmd cmd = { 108 struct iwl_host_cmd cmd = {
109 .id = REPLY_LEDS_CMD, 109 .id = REPLY_LEDS_CMD,
110 .len = sizeof(struct iwl_led_cmd), 110 .len = { sizeof(struct iwl_led_cmd), },
111 .data = led_cmd, 111 .data = { led_cmd, },
112 .flags = CMD_ASYNC, 112 .flags = CMD_ASYNC,
113 .callback = NULL, 113 .callback = NULL,
114 }; 114 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 3c8cebde16cc..7df2814fd4f8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -141,7 +141,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
141 struct iwl_host_cmd cmd = { 141 struct iwl_host_cmd cmd = {
142 .id = REPLY_ADD_STA, 142 .id = REPLY_ADD_STA,
143 .flags = flags, 143 .flags = flags,
144 .data = data, 144 .data = { data, },
145 }; 145 };
146 u8 sta_id __maybe_unused = sta->sta.sta_id; 146 u8 sta_id __maybe_unused = sta->sta.sta_id;
147 147
@@ -155,7 +155,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
155 might_sleep(); 155 might_sleep();
156 } 156 }
157 157
158 cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); 158 cmd.len[0] = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
159 ret = iwl_send_cmd(priv, &cmd); 159 ret = iwl_send_cmd(priv, &cmd);
160 160
161 if (ret || (flags & CMD_ASYNC)) 161 if (ret || (flags & CMD_ASYNC))
@@ -401,9 +401,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
401 401
402 struct iwl_host_cmd cmd = { 402 struct iwl_host_cmd cmd = {
403 .id = REPLY_REMOVE_STA, 403 .id = REPLY_REMOVE_STA,
404 .len = sizeof(struct iwl_rem_sta_cmd), 404 .len = { sizeof(struct iwl_rem_sta_cmd), },
405 .flags = CMD_SYNC, 405 .flags = CMD_SYNC,
406 .data = &rm_sta_cmd, 406 .data = { &rm_sta_cmd, },
407 }; 407 };
408 408
409 memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); 409 memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
@@ -760,9 +760,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
760 760
761 struct iwl_host_cmd cmd = { 761 struct iwl_host_cmd cmd = {
762 .id = REPLY_TX_LINK_QUALITY_CMD, 762 .id = REPLY_TX_LINK_QUALITY_CMD,
763 .len = sizeof(struct iwl_link_quality_cmd), 763 .len = { sizeof(struct iwl_link_quality_cmd), },
764 .flags = flags, 764 .flags = flags,
765 .data = lq, 765 .data = { lq, },
766 }; 766 };
767 767
768 if (WARN_ON(lq->sta_id == IWL_INVALID_STATION)) 768 if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
index 89b6696622c1..69b7e6bf2d6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
@@ -97,6 +97,13 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
97 97
98 [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, 98 [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, },
99 [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, 99 [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, },
100
101 [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
102
103 [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
104 [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, },
105
106 [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
100}; 107};
101 108
102/* 109/*
@@ -167,6 +174,31 @@ nla_put_failure:
167void iwl_testmode_init(struct iwl_priv *priv) 174void iwl_testmode_init(struct iwl_priv *priv)
168{ 175{
169 priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; 176 priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
177 priv->testmode_trace.trace_enabled = false;
178}
179
180static void iwl_trace_cleanup(struct iwl_priv *priv)
181{
182 struct device *dev = &priv->pci_dev->dev;
183
184 if (priv->testmode_trace.trace_enabled) {
185 if (priv->testmode_trace.cpu_addr &&
186 priv->testmode_trace.dma_addr)
187 dma_free_coherent(dev,
188 TRACE_TOTAL_SIZE,
189 priv->testmode_trace.cpu_addr,
190 priv->testmode_trace.dma_addr);
191 priv->testmode_trace.trace_enabled = false;
192 priv->testmode_trace.cpu_addr = NULL;
193 priv->testmode_trace.trace_addr = NULL;
194 priv->testmode_trace.dma_addr = 0;
195 }
196}
197
198
199void iwl_testmode_cleanup(struct iwl_priv *priv)
200{
201 iwl_trace_cleanup(priv);
170} 202}
171 203
172/* 204/*
@@ -198,10 +230,11 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
198 } 230 }
199 231
200 cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); 232 cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
201 cmd.data = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); 233 cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
202 cmd.len = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); 234 cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
235 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
203 IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," 236 IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
204 " len %d\n", cmd.id, cmd.flags, cmd.len); 237 " len %d\n", cmd.id, cmd.flags, cmd.len[0]);
205 /* ok, let's submit the command to ucode */ 238 /* ok, let's submit the command to ucode */
206 return iwl_send_cmd(priv, &cmd); 239 return iwl_send_cmd(priv, &cmd);
207} 240}
@@ -388,6 +421,38 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
388 "Error starting the device: %d\n", status); 421 "Error starting the device: %d\n", status);
389 break; 422 break;
390 423
424 case IWL_TM_CMD_APP2DEV_GET_EEPROM:
425 if (priv->eeprom) {
426 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
427 priv->cfg->base_params->eeprom_size + 20);
428 if (!skb) {
429 IWL_DEBUG_INFO(priv,
430 "Error allocating memory\n");
431 return -ENOMEM;
432 }
433 NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
434 IWL_TM_CMD_DEV2APP_EEPROM_RSP);
435 NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
436 priv->cfg->base_params->eeprom_size,
437 priv->eeprom);
438 status = cfg80211_testmode_reply(skb);
439 if (status < 0)
440 IWL_DEBUG_INFO(priv,
441 "Error sending msg : %d\n",
442 status);
443 } else
444 return -EFAULT;
445 break;
446
447 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
448 if (!tb[IWL_TM_ATTR_FIXRATE]) {
449 IWL_DEBUG_INFO(priv,
450 "Error finding fixrate setting\n");
451 return -ENOMSG;
452 }
453 priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
454 break;
455
391 default: 456 default:
392 IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); 457 IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
393 return -ENOSYS; 458 return -ENOSYS;
@@ -399,6 +464,102 @@ nla_put_failure:
399 return -EMSGSIZE; 464 return -EMSGSIZE;
400} 465}
401 466
467
468/*
469 * This function handles the user application commands for uCode trace
470 *
471 * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
472 * handlers respectively.
473 *
474 * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
475 * value of the actual command execution is replied to the user application.
476 *
477 * @hw: ieee80211_hw object that represents the device
478 * @tb: gnl message fields from the user space
479 */
480static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
481{
482 struct iwl_priv *priv = hw->priv;
483 struct sk_buff *skb;
484 int status = 0;
485 struct device *dev = &priv->pci_dev->dev;
486
487 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
488 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
489 if (priv->testmode_trace.trace_enabled)
490 return -EBUSY;
491
492 priv->testmode_trace.cpu_addr =
493 dma_alloc_coherent(dev,
494 TRACE_TOTAL_SIZE,
495 &priv->testmode_trace.dma_addr,
496 GFP_KERNEL);
497 if (!priv->testmode_trace.cpu_addr)
498 return -ENOMEM;
499 priv->testmode_trace.trace_enabled = true;
500 priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
501 priv->testmode_trace.cpu_addr, 0x100);
502 memset(priv->testmode_trace.trace_addr, 0x03B,
503 TRACE_BUFF_SIZE);
504 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
505 sizeof(priv->testmode_trace.dma_addr) + 20);
506 if (!skb) {
507 IWL_DEBUG_INFO(priv,
508 "Error allocating memory\n");
509 iwl_trace_cleanup(priv);
510 return -ENOMEM;
511 }
512 NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR,
513 sizeof(priv->testmode_trace.dma_addr),
514 (u64 *)&priv->testmode_trace.dma_addr);
515 status = cfg80211_testmode_reply(skb);
516 if (status < 0) {
517 IWL_DEBUG_INFO(priv,
518 "Error sending msg : %d\n",
519 status);
520 }
521 break;
522
523 case IWL_TM_CMD_APP2DEV_END_TRACE:
524 iwl_trace_cleanup(priv);
525 break;
526
527 case IWL_TM_CMD_APP2DEV_READ_TRACE:
528 if (priv->testmode_trace.trace_enabled &&
529 priv->testmode_trace.trace_addr) {
530 skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
531 20 + TRACE_BUFF_SIZE);
532 if (skb == NULL) {
533 IWL_DEBUG_INFO(priv,
534 "Error allocating memory\n");
535 return -ENOMEM;
536 }
537 NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
538 TRACE_BUFF_SIZE,
539 priv->testmode_trace.trace_addr);
540 status = cfg80211_testmode_reply(skb);
541 if (status < 0) {
542 IWL_DEBUG_INFO(priv,
543 "Error sending msg : %d\n", status);
544 }
545 } else
546 return -EFAULT;
547 break;
548
549 default:
550 IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
551 return -ENOSYS;
552 }
553 return status;
554
555nla_put_failure:
556 kfree_skb(skb);
557 if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) ==
558 IWL_TM_CMD_APP2DEV_BEGIN_TRACE)
559 iwl_trace_cleanup(priv);
560 return -EMSGSIZE;
561}
562
402/* The testmode gnl message handler that takes the gnl message from the 563/* The testmode gnl message handler that takes the gnl message from the
403 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then 564 * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
404 * invoke the corresponding handlers. 565 * invoke the corresponding handlers.
@@ -455,9 +616,19 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
455 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: 616 case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
456 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: 617 case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
457 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: 618 case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
619 case IWL_TM_CMD_APP2DEV_GET_EEPROM:
620 case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
458 IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); 621 IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
459 result = iwl_testmode_driver(hw, tb); 622 result = iwl_testmode_driver(hw, tb);
460 break; 623 break;
624
625 case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
626 case IWL_TM_CMD_APP2DEV_END_TRACE:
627 case IWL_TM_CMD_APP2DEV_READ_TRACE:
628 IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n");
629 result = iwl_testmode_trace(hw, tb);
630 break;
631
461 default: 632 default:
462 IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); 633 IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
463 result = -ENOSYS; 634 result = -ENOSYS;
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index 31f8949f2801..a88085e9b361 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -88,9 +88,15 @@ enum iwl_tm_cmd_t {
88 IWL_TM_CMD_APP2DEV_LOAD_INIT_FW, 88 IWL_TM_CMD_APP2DEV_LOAD_INIT_FW,
89 IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB, 89 IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB,
90 IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW, 90 IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW,
91 IWL_TM_CMD_APP2DEV_GET_EEPROM,
92 IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
91 /* if there is other new command for the driver layer operation, 93 /* if there is other new command for the driver layer operation,
92 * append them here */ 94 * append them here */
93 95
96 /* commands fom user space for uCode trace operations */
97 IWL_TM_CMD_APP2DEV_BEGIN_TRACE,
98 IWL_TM_CMD_APP2DEV_END_TRACE,
99 IWL_TM_CMD_APP2DEV_READ_TRACE,
94 100
95 /* commands from kernel space to carry the synchronous response 101 /* commands from kernel space to carry the synchronous response
96 * to user application */ 102 * to user application */
@@ -99,6 +105,11 @@ enum iwl_tm_cmd_t {
99 /* commands from kernel space to multicast the spontaneous messages 105 /* commands from kernel space to multicast the spontaneous messages
100 * to user application */ 106 * to user application */
101 IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, 107 IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
108
109 /* commands from kernel space to carry the eeprom response
110 * to user application */
111 IWL_TM_CMD_DEV2APP_EEPROM_RSP,
112
102 IWL_TM_CMD_MAX, 113 IWL_TM_CMD_MAX,
103}; 114};
104 115
@@ -144,8 +155,31 @@ enum iwl_tm_attr_t {
144 * application */ 155 * application */
145 IWL_TM_ATTR_UCODE_RX_PKT, 156 IWL_TM_ATTR_UCODE_RX_PKT,
146 157
158 /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,
159 * The mandatory fields are:
160 * IWL_TM_ATTR_EEPROM for the data content responging to the user
161 * application */
162 IWL_TM_ATTR_EEPROM,
163
164 /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,
165 * The mandatory fields are:
166 * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
167 */
168 IWL_TM_ATTR_TRACE_ADDR,
169 IWL_TM_ATTR_TRACE_DATA,
170
171 /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
172 * The mandatory fields are:
173 * IWL_TM_ATTR_FIXRATE for the fixed rate
174 */
175 IWL_TM_ATTR_FIXRATE,
176
147 IWL_TM_ATTR_MAX, 177 IWL_TM_ATTR_MAX,
148}; 178};
149 179
180/* uCode trace buffer */
181#define TRACE_BUFF_SIZE 0x20000
182#define TRACE_BUFF_PADD 0x2000
183#define TRACE_TOTAL_SIZE (TRACE_BUFF_SIZE + TRACE_BUFF_PADD)
150 184
151#endif 185#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index e69597ea43e2..54a935ff38fa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -32,6 +32,7 @@
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <net/mac80211.h> 33#include <net/mac80211.h>
34#include "iwl-eeprom.h" 34#include "iwl-eeprom.h"
35#include "iwl-agn.h"
35#include "iwl-dev.h" 36#include "iwl-dev.h"
36#include "iwl-core.h" 37#include "iwl-core.h"
37#include "iwl-sta.h" 38#include "iwl-sta.h"
@@ -85,6 +86,158 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
85 txq->need_update = 0; 86 txq->need_update = 0;
86} 87}
87 88
89static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
90{
91 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
92
93 dma_addr_t addr = get_unaligned_le32(&tb->lo);
94 if (sizeof(dma_addr_t) > sizeof(u32))
95 addr |=
96 ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
97
98 return addr;
99}
100
101static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
102{
103 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
104
105 return le16_to_cpu(tb->hi_n_len) >> 4;
106}
107
108static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
109 dma_addr_t addr, u16 len)
110{
111 struct iwl_tfd_tb *tb = &tfd->tbs[idx];
112 u16 hi_n_len = len << 4;
113
114 put_unaligned_le32(addr, &tb->lo);
115 if (sizeof(dma_addr_t) > sizeof(u32))
116 hi_n_len |= ((addr >> 16) >> 16) & 0xF;
117
118 tb->hi_n_len = cpu_to_le16(hi_n_len);
119
120 tfd->num_tbs = idx + 1;
121}
122
123static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
124{
125 return tfd->num_tbs & 0x1f;
126}
127
128static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
129 struct iwl_tfd *tfd)
130{
131 struct pci_dev *dev = priv->pci_dev;
132 int i;
133 int num_tbs;
134
135 /* Sanity check on number of chunks */
136 num_tbs = iwl_tfd_get_num_tbs(tfd);
137
138 if (num_tbs >= IWL_NUM_OF_TBS) {
139 IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
140 /* @todo issue fatal error, it is quite serious situation */
141 return;
142 }
143
144 /* Unmap tx_cmd */
145 if (num_tbs)
146 pci_unmap_single(dev,
147 dma_unmap_addr(meta, mapping),
148 dma_unmap_len(meta, len),
149 PCI_DMA_BIDIRECTIONAL);
150
151 /* Unmap chunks, if any. */
152 for (i = 1; i < num_tbs; i++)
153 pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
154 iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);
155}
156
157/**
158 * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
159 * @priv - driver private data
160 * @txq - tx queue
161 *
162 * Does NOT advance any TFD circular buffer read/write indexes
163 * Does NOT free the TFD itself (which is within circular buffer)
164 */
165void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
166{
167 struct iwl_tfd *tfd_tmp = txq->tfds;
168 int index = txq->q.read_ptr;
169
170 iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index]);
171
172 /* free SKB */
173 if (txq->txb) {
174 struct sk_buff *skb;
175
176 skb = txq->txb[txq->q.read_ptr].skb;
177
178 /* can be called from irqs-disabled context */
179 if (skb) {
180 dev_kfree_skb_any(skb);
181 txq->txb[txq->q.read_ptr].skb = NULL;
182 }
183 }
184}
185
186int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
187 struct iwl_tx_queue *txq,
188 dma_addr_t addr, u16 len,
189 u8 reset)
190{
191 struct iwl_queue *q;
192 struct iwl_tfd *tfd, *tfd_tmp;
193 u32 num_tbs;
194
195 q = &txq->q;
196 tfd_tmp = txq->tfds;
197 tfd = &tfd_tmp[q->write_ptr];
198
199 if (reset)
200 memset(tfd, 0, sizeof(*tfd));
201
202 num_tbs = iwl_tfd_get_num_tbs(tfd);
203
204 /* Each TFD can point to a maximum 20 Tx buffers */
205 if (num_tbs >= IWL_NUM_OF_TBS) {
206 IWL_ERR(priv, "Error can not send more than %d chunks\n",
207 IWL_NUM_OF_TBS);
208 return -EINVAL;
209 }
210
211 if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
212 return -EINVAL;
213
214 if (unlikely(addr & ~IWL_TX_DMA_MASK))
215 IWL_ERR(priv, "Unaligned address = %llx\n",
216 (unsigned long long)addr);
217
218 iwl_tfd_set_tb(tfd, num_tbs, addr, len);
219
220 return 0;
221}
222
223/*
224 * Tell nic where to find circular buffer of Tx Frame Descriptors for
225 * given Tx queue, and enable the DMA channel used for that queue.
226 *
227 * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
228 * channels supported in hardware.
229 */
230static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
231{
232 int txq_id = txq->q.id;
233
234 /* Circular buffer (TFD queue in DRAM) physical base address */
235 iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
236 txq->q.dma_addr >> 8);
237
238 return 0;
239}
240
88/** 241/**
89 * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's 242 * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's
90 */ 243 */
@@ -97,7 +250,7 @@ void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
97 return; 250 return;
98 251
99 while (q->write_ptr != q->read_ptr) { 252 while (q->write_ptr != q->read_ptr) {
100 priv->cfg->ops->lib->txq_free_tfd(priv, txq); 253 iwlagn_txq_free_tfd(priv, txq);
101 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); 254 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
102 } 255 }
103} 256}
@@ -154,7 +307,7 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv)
154 return; 307 return;
155 308
156 while (q->read_ptr != q->write_ptr) { 309 while (q->read_ptr != q->write_ptr) {
157 i = get_cmd_index(q, q->read_ptr, 0); 310 i = get_cmd_index(q, q->read_ptr);
158 311
159 if (txq->meta[i].flags & CMD_MAPPED) { 312 if (txq->meta[i].flags & CMD_MAPPED) {
160 pci_unmap_single(priv->pci_dev, 313 pci_unmap_single(priv->pci_dev,
@@ -166,15 +319,6 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv)
166 319
167 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); 320 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
168 } 321 }
169
170 i = q->n_window;
171 if (txq->meta[i].flags & CMD_MAPPED) {
172 pci_unmap_single(priv->pci_dev,
173 dma_unmap_addr(&txq->meta[i], mapping),
174 dma_unmap_len(&txq->meta[i], len),
175 PCI_DMA_BIDIRECTIONAL);
176 txq->meta[i].flags = 0;
177 }
178} 322}
179 323
180/** 324/**
@@ -194,7 +338,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
194 iwl_cmd_queue_unmap(priv); 338 iwl_cmd_queue_unmap(priv);
195 339
196 /* De-alloc array of command/tx buffers */ 340 /* De-alloc array of command/tx buffers */
197 for (i = 0; i <= TFD_CMD_SLOTS; i++) 341 for (i = 0; i < TFD_CMD_SLOTS; i++)
198 kfree(txq->cmd[i]); 342 kfree(txq->cmd[i]);
199 343
200 /* De-alloc circular buffer of TFDs */ 344 /* De-alloc circular buffer of TFDs */
@@ -334,33 +478,17 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
334{ 478{
335 int i, len; 479 int i, len;
336 int ret; 480 int ret;
337 int actual_slots = slots_num;
338
339 /*
340 * Alloc buffer array for commands (Tx or other types of commands).
341 * For the command queue (#4/#9), allocate command space + one big
342 * command for scan, since scan command is very huge; the system will
343 * not have two scans at the same time, so only one is needed.
344 * For normal Tx queues (all other queues), no super-size command
345 * space is needed.
346 */
347 if (txq_id == priv->cmd_queue)
348 actual_slots++;
349 481
350 txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots, 482 txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num,
351 GFP_KERNEL); 483 GFP_KERNEL);
352 txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots, 484 txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num,
353 GFP_KERNEL); 485 GFP_KERNEL);
354 486
355 if (!txq->meta || !txq->cmd) 487 if (!txq->meta || !txq->cmd)
356 goto out_free_arrays; 488 goto out_free_arrays;
357 489
358 len = sizeof(struct iwl_device_cmd); 490 len = sizeof(struct iwl_device_cmd);
359 for (i = 0; i < actual_slots; i++) { 491 for (i = 0; i < slots_num; i++) {
360 /* only happens for cmd queue */
361 if (i == slots_num)
362 len = IWL_MAX_CMD_SIZE;
363
364 txq->cmd[i] = kmalloc(len, GFP_KERNEL); 492 txq->cmd[i] = kmalloc(len, GFP_KERNEL);
365 if (!txq->cmd[i]) 493 if (!txq->cmd[i])
366 goto err; 494 goto err;
@@ -391,11 +519,11 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
391 return ret; 519 return ret;
392 520
393 /* Tell device where to find queue */ 521 /* Tell device where to find queue */
394 priv->cfg->ops->lib->txq_init(priv, txq); 522 iwlagn_tx_queue_init(priv, txq);
395 523
396 return 0; 524 return 0;
397err: 525err:
398 for (i = 0; i < actual_slots; i++) 526 for (i = 0; i < slots_num; i++)
399 kfree(txq->cmd[i]); 527 kfree(txq->cmd[i]);
400out_free_arrays: 528out_free_arrays:
401 kfree(txq->meta); 529 kfree(txq->meta);
@@ -420,7 +548,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
420 iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); 548 iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
421 549
422 /* Tell device where to find queue */ 550 /* Tell device where to find queue */
423 priv->cfg->ops->lib->txq_init(priv, txq); 551 iwlagn_tx_queue_init(priv, txq);
424} 552}
425 553
426/*************** HOST COMMAND QUEUE FUNCTIONS *****/ 554/*************** HOST COMMAND QUEUE FUNCTIONS *****/
@@ -443,23 +571,49 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
443 dma_addr_t phys_addr; 571 dma_addr_t phys_addr;
444 unsigned long flags; 572 unsigned long flags;
445 u32 idx; 573 u32 idx;
446 u16 fix_size; 574 u16 copy_size, cmd_size;
447 bool is_ct_kill = false; 575 bool is_ct_kill = false;
576 bool had_nocopy = false;
577 int i;
578 u8 *cmd_dest;
579#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
580 const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
581 int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
582 int trace_idx;
583#endif
584
585 if (test_bit(STATUS_FW_ERROR, &priv->status)) {
586 IWL_WARN(priv, "fw recovery, no hcmd send\n");
587 return -EIO;
588 }
448 589
449 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); 590 copy_size = sizeof(out_cmd->hdr);
591 cmd_size = sizeof(out_cmd->hdr);
592
593 /* need one for the header if the first is NOCOPY */
594 BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
595
596 for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
597 if (!cmd->len[i])
598 continue;
599 if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
600 had_nocopy = true;
601 } else {
602 /* NOCOPY must not be followed by normal! */
603 if (WARN_ON(had_nocopy))
604 return -EINVAL;
605 copy_size += cmd->len[i];
606 }
607 cmd_size += cmd->len[i];
608 }
450 609
451 /* 610 /*
452 * If any of the command structures end up being larger than 611 * If any of the command structures end up being larger than
453 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then 612 * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically
454 * we will need to increase the size of the TFD entries 613 * allocated into separate TFDs, then we will need to
455 * Also, check to see if command buffer should not exceed the size 614 * increase the size of the buffers.
456 * of device_cmd and max_cmd_size.
457 */ 615 */
458 if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && 616 if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
459 !(cmd->flags & CMD_SIZE_HUGE)))
460 return -EINVAL;
461
462 if (WARN_ON(fix_size > IWL_MAX_CMD_SIZE))
463 return -EINVAL; 617 return -EINVAL;
464 618
465 if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { 619 if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
@@ -468,14 +622,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
468 return -EIO; 622 return -EIO;
469 } 623 }
470 624
471 /*
472 * As we only have a single huge buffer, check that the command
473 * is synchronous (otherwise buffers could end up being reused).
474 */
475
476 if (WARN_ON((cmd->flags & CMD_ASYNC) && (cmd->flags & CMD_SIZE_HUGE)))
477 return -EINVAL;
478
479 spin_lock_irqsave(&priv->hcmd_lock, flags); 625 spin_lock_irqsave(&priv->hcmd_lock, flags);
480 626
481 if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { 627 if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
@@ -490,7 +636,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
490 return -ENOSPC; 636 return -ENOSPC;
491 } 637 }
492 638
493 idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); 639 idx = get_cmd_index(q, q->write_ptr);
494 out_cmd = txq->cmd[idx]; 640 out_cmd = txq->cmd[idx];
495 out_meta = &txq->meta[idx]; 641 out_meta = &txq->meta[idx];
496 642
@@ -505,57 +651,84 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
505 if (cmd->flags & CMD_ASYNC) 651 if (cmd->flags & CMD_ASYNC)
506 out_meta->callback = cmd->callback; 652 out_meta->callback = cmd->callback;
507 653
508 out_cmd->hdr.cmd = cmd->id; 654 /* set up the header */
509 memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
510
511 /* At this point, the out_cmd now has all of the incoming cmd
512 * information */
513 655
656 out_cmd->hdr.cmd = cmd->id;
514 out_cmd->hdr.flags = 0; 657 out_cmd->hdr.flags = 0;
515 out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | 658 out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
516 INDEX_TO_SEQ(q->write_ptr)); 659 INDEX_TO_SEQ(q->write_ptr));
517 if (cmd->flags & CMD_SIZE_HUGE) 660
518 out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; 661 /* and copy the data that needs to be copied */
519 662
520#ifdef CONFIG_IWLWIFI_DEBUG 663 cmd_dest = &out_cmd->cmd.payload[0];
521 switch (out_cmd->hdr.cmd) { 664 for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
522 case REPLY_TX_LINK_QUALITY_CMD: 665 if (!cmd->len[i])
523 case SENSITIVITY_CMD: 666 continue;
524 IWL_DEBUG_HC_DUMP(priv, "Sending command %s (#%x), seq: 0x%04X, " 667 if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
525 "%d bytes at %d[%d]:%d\n", 668 break;
526 get_cmd_string(out_cmd->hdr.cmd), 669 memcpy(cmd_dest, cmd->data[i], cmd->len[i]);
527 out_cmd->hdr.cmd, 670 cmd_dest += cmd->len[i];
528 le16_to_cpu(out_cmd->hdr.sequence), fix_size,
529 q->write_ptr, idx, priv->cmd_queue);
530 break;
531 default:
532 IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
533 "%d bytes at %d[%d]:%d\n",
534 get_cmd_string(out_cmd->hdr.cmd),
535 out_cmd->hdr.cmd,
536 le16_to_cpu(out_cmd->hdr.sequence), fix_size,
537 q->write_ptr, idx, priv->cmd_queue);
538 } 671 }
539#endif 672
673 IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
674 "%d bytes at %d[%d]:%d\n",
675 get_cmd_string(out_cmd->hdr.cmd),
676 out_cmd->hdr.cmd,
677 le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
678 q->write_ptr, idx, priv->cmd_queue);
679
540 phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, 680 phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
541 fix_size, PCI_DMA_BIDIRECTIONAL); 681 copy_size, PCI_DMA_BIDIRECTIONAL);
542 if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { 682 if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
543 idx = -ENOMEM; 683 idx = -ENOMEM;
544 goto out; 684 goto out;
545 } 685 }
546 686
547 dma_unmap_addr_set(out_meta, mapping, phys_addr); 687 dma_unmap_addr_set(out_meta, mapping, phys_addr);
548 dma_unmap_len_set(out_meta, len, fix_size); 688 dma_unmap_len_set(out_meta, len, copy_size);
689
690 iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1);
691#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
692 trace_bufs[0] = &out_cmd->hdr;
693 trace_lens[0] = copy_size;
694 trace_idx = 1;
695#endif
696
697 for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
698 if (!cmd->len[i])
699 continue;
700 if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
701 continue;
702 phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i],
703 cmd->len[i], PCI_DMA_TODEVICE);
704 if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) {
705 iwlagn_unmap_tfd(priv, out_meta,
706 &txq->tfds[q->write_ptr]);
707 idx = -ENOMEM;
708 goto out;
709 }
710
711 iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
712 cmd->len[i], 0);
713#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
714 trace_bufs[trace_idx] = cmd->data[i];
715 trace_lens[trace_idx] = cmd->len[i];
716 trace_idx++;
717#endif
718 }
549 719
550 out_meta->flags = cmd->flags | CMD_MAPPED; 720 out_meta->flags = cmd->flags | CMD_MAPPED;
551 721
552 txq->need_update = 1; 722 txq->need_update = 1;
553 723
554 trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); 724 /* check that tracing gets all possible blocks */
555 725 BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
556 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, 726#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
557 phys_addr, fix_size, 1, 727 trace_iwlwifi_dev_hcmd(priv, cmd->flags,
558 U32_PAD(cmd->len)); 728 trace_bufs[0], trace_lens[0],
729 trace_bufs[1], trace_lens[1],
730 trace_bufs[2], trace_lens[2]);
731#endif
559 732
560 /* Increment and update queue's write index */ 733 /* Increment and update queue's write index */
561 q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); 734 q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
@@ -614,7 +787,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
614 int txq_id = SEQ_TO_QUEUE(sequence); 787 int txq_id = SEQ_TO_QUEUE(sequence);
615 int index = SEQ_TO_INDEX(sequence); 788 int index = SEQ_TO_INDEX(sequence);
616 int cmd_index; 789 int cmd_index;
617 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
618 struct iwl_device_cmd *cmd; 790 struct iwl_device_cmd *cmd;
619 struct iwl_cmd_meta *meta; 791 struct iwl_cmd_meta *meta;
620 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; 792 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
@@ -632,14 +804,11 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
632 return; 804 return;
633 } 805 }
634 806
635 cmd_index = get_cmd_index(&txq->q, index, huge); 807 cmd_index = get_cmd_index(&txq->q, index);
636 cmd = txq->cmd[cmd_index]; 808 cmd = txq->cmd[cmd_index];
637 meta = &txq->meta[cmd_index]; 809 meta = &txq->meta[cmd_index];
638 810
639 pci_unmap_single(priv->pci_dev, 811 iwlagn_unmap_tfd(priv, meta, &txq->tfds[index]);
640 dma_unmap_addr(meta, mapping),
641 dma_unmap_len(meta, len),
642 PCI_DMA_BIDIRECTIONAL);
643 812
644 /* Input error checking is done when commands are added to queue. */ 813 /* Input error checking is done when commands are added to queue. */
645 if (meta->flags & CMD_WANT_SKB) { 814 if (meta->flags & CMD_WANT_SKB) {