diff options
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 | ||
172 | static struct iwl_lib_ops iwl1000_lib = { | 172 | static 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 | ||
253 | static struct iwl_lib_ops iwl2000_lib = { | 253 | static 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 | ||
340 | static struct iwl_lib_ops iwl5000_lib = { | 340 | static 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 | ||
375 | static struct iwl_lib_ops iwl5150_lib = { | 371 | static 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 | ||
279 | static struct iwl_lib_ops iwl6000_lib = { | 279 | static 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 | ||
315 | static struct iwl_lib_ops iwl6030_lib = { | 311 | static 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) | ||
339 | static 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 | */ |
2173 | static u32 rs_update_rate_tbl(struct iwl_priv *priv, | 2202 | static 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, | |||
2541 | lq_update: | 2567 | lq_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 |
3050 | static int open_file_generic(struct inode *inode, struct file *file) | 3075 | static 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 = { | |||
3254 | static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, | 3266 | static 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 | |||
203 | static 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 | |||
215 | static 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 | |||
222 | static 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 | |||
237 | static 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 | */ | ||
250 | void 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 | |||
296 | int 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 | */ | ||
340 | int 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 | ||
352 | static void iwl_bg_beacon_update(struct work_struct *work) | 198 | static void iwl_bg_beacon_update(struct work_struct *work) |
@@ -1776,10 +1622,7 @@ static const char *desc_lookup(u32 num) | |||
1776 | 1622 | ||
1777 | void iwl_dump_nic_error_log(struct iwl_priv *priv) | 1623 | void 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 | ||
3400 | struct ieee80211_ops iwlagn_hw_ops = { | 3247 | struct 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); | |||
191 | void iwl_setup_rx_handlers(struct iwl_priv *priv); | 191 | void iwl_setup_rx_handlers(struct iwl_priv *priv); |
192 | 192 | ||
193 | /* tx */ | 193 | /* tx */ |
194 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 194 | void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
195 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 195 | int 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); |
198 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | ||
199 | struct iwl_tx_queue *txq); | ||
200 | void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | 198 | void 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); |
202 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | 200 | int 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 |
346 | extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); | 344 | extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); |
347 | extern void iwl_testmode_init(struct iwl_priv *priv); | 345 | extern void iwl_testmode_init(struct iwl_priv *priv); |
346 | extern void iwl_testmode_cleanup(struct iwl_priv *priv); | ||
348 | #else | 347 | #else |
349 | static inline | 348 | static inline |
350 | int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) | 349 | int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) |
@@ -355,6 +354,10 @@ static inline | |||
355 | void iwl_testmode_init(struct iwl_priv *priv) | 354 | void iwl_testmode_init(struct iwl_priv *priv) |
356 | { | 355 | { |
357 | } | 356 | } |
357 | static inline | ||
358 | void 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 { | |||
127 | struct iwl_lib_ops { | 127 | struct 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 | |||
53 | struct iwl_tx_queue; | 51 | struct 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 | */ |
128 | struct iwl_queue { | 140 | struct 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 | ||
166 | struct iwl_tx_queue { | 178 | struct 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 | */ |
265 | struct iwl_device_cmd { | 276 | struct 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 | |||
293 | enum iwl_hcmd_dataflag { | ||
294 | IWL_HCMD_DFL_NOCOPY = BIT(0), | ||
295 | }; | ||
280 | 296 | ||
281 | struct iwl_host_cmd { | 297 | struct 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 | ||
691 | static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) | 708 | static 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 | ||
1183 | struct iwl_testmode_trace { | ||
1184 | u8 *cpu_addr; | ||
1185 | u8 *trace_addr; | ||
1186 | dma_addr_t dma_addr; | ||
1187 | bool trace_enabled; | ||
1188 | }; | ||
1189 | #endif | ||
1174 | struct iwl_priv { | 1190 | struct 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 | ||
1506 | static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) | 1528 | static 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 | ||
139 | TRACE_EVENT(iwlwifi_dev_hcmd, | 139 | TRACE_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 | ||
204 | TRACE_EVENT(iwlwifi_dev_ucode_error, | 211 | TRACE_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 | ||
241 | TRACE_EVENT(iwlwifi_dev_ucode_event, | 271 | TRACE_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 | ||
217 | static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) | 217 | static 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 | ||
230 | static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) | 229 | static 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: | |||
167 | void iwl_testmode_init(struct iwl_priv *priv) | 174 | void 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 | |||
180 | static 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 | |||
199 | void 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 | */ | ||
480 | static 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 | |||
555 | nla_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 | ||
89 | static 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 | |||
101 | static 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 | |||
108 | static 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 | |||
123 | static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) | ||
124 | { | ||
125 | return tfd->num_tbs & 0x1f; | ||
126 | } | ||
127 | |||
128 | static 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 | */ | ||
165 | void 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 | |||
186 | int 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 | */ | ||
230 | static 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; |
397 | err: | 525 | err: |
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]); |
400 | out_free_arrays: | 528 | out_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) { |