diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-03-10 16:00:07 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-03-12 14:21:56 -0400 |
commit | d663ee73f62903aed334eca25832a76c4a7e4c1c (patch) | |
tree | 3a8885ee9ddae0c6c18097f2530c42d221e433b0 | |
parent | 10d8f31ebbd6ea9aa8d65d2f04ebef63225052de (diff) |
iwlwifi: abstract out missing SEQ_RX_FRAME workaround
Mohammed Shafi ran into [1] the SEQ_RX_FRAME workaround
warning with a statistics notification, this means we
can't just remove it as we'd hoped.
Abstract it out so that the higher layer can configure
this as a kind of "filter" in the transport.
[1] http://mid.gmane.org/CAD2nsn1_DzbRHuSbS_1rFNzuux_9pW1-pABEasQ01_y7-ndO5w@mail.gmail.com
Reported-by: Mohammed Shafi <shafi.wireless@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 29 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 9 |
5 files changed, 39 insertions, 18 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 28422c03d673..5ef15855be2f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -1186,6 +1186,14 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1186 | u16 num_mac; | 1186 | u16 num_mac; |
1187 | u32 ucode_flags; | 1187 | u32 ucode_flags; |
1188 | struct iwl_trans_config trans_cfg; | 1188 | struct iwl_trans_config trans_cfg; |
1189 | static const u8 no_reclaim_cmds[] = { | ||
1190 | REPLY_RX_PHY_CMD, | ||
1191 | REPLY_RX, | ||
1192 | REPLY_RX_MPDU_CMD, | ||
1193 | REPLY_COMPRESSED_BA, | ||
1194 | STATISTICS_NOTIFICATION, | ||
1195 | REPLY_TX, | ||
1196 | }; | ||
1189 | 1197 | ||
1190 | /************************ | 1198 | /************************ |
1191 | * 1. Allocating HW data | 1199 | * 1. Allocating HW data |
@@ -1211,6 +1219,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1211 | * to know about. | 1219 | * to know about. |
1212 | */ | 1220 | */ |
1213 | trans_cfg.op_mode = op_mode; | 1221 | trans_cfg.op_mode = op_mode; |
1222 | trans_cfg.no_reclaim_cmds = no_reclaim_cmds; | ||
1223 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); | ||
1214 | 1224 | ||
1215 | ucode_flags = fw->ucode_capa.flags; | 1225 | ucode_flags = fw->ucode_capa.flags; |
1216 | 1226 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 67965599bb30..1c2fe87bd7e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | |||
@@ -291,6 +291,8 @@ struct iwl_trans_pcie { | |||
291 | wait_queue_head_t ucode_write_waitq; | 291 | wait_queue_head_t ucode_write_waitq; |
292 | unsigned long status; | 292 | unsigned long status; |
293 | u8 cmd_queue; | 293 | u8 cmd_queue; |
294 | u8 n_no_reclaim_cmds; | ||
295 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; | ||
294 | }; | 296 | }; |
295 | 297 | ||
296 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 298 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 9bc3c73af5e9..8bec0e1ccb54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | |||
@@ -395,13 +395,17 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
395 | * there is no command buffer to reclaim. | 395 | * there is no command buffer to reclaim. |
396 | * Ucode should set SEQ_RX_FRAME bit if ucode-originated, | 396 | * Ucode should set SEQ_RX_FRAME bit if ucode-originated, |
397 | * but apparently a few don't get set; catch them here. */ | 397 | * but apparently a few don't get set; catch them here. */ |
398 | reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && | 398 | reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME); |
399 | (pkt->hdr.cmd != REPLY_RX_PHY_CMD) && | 399 | if (reclaim) { |
400 | (pkt->hdr.cmd != REPLY_RX) && | 400 | int i; |
401 | (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) && | 401 | |
402 | (pkt->hdr.cmd != REPLY_COMPRESSED_BA) && | 402 | for (i = 0; i < trans_pcie->n_no_reclaim_cmds; i++) { |
403 | (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && | 403 | if (trans_pcie->no_reclaim_cmds[i] == pkt->hdr.cmd) { |
404 | (pkt->hdr.cmd != REPLY_TX); | 404 | reclaim = false; |
405 | break; | ||
406 | } | ||
407 | } | ||
408 | } | ||
405 | 409 | ||
406 | sequence = le16_to_cpu(pkt->hdr.sequence); | 410 | sequence = le16_to_cpu(pkt->hdr.sequence); |
407 | index = SEQ_TO_INDEX(sequence); | 411 | index = SEQ_TO_INDEX(sequence); |
@@ -412,17 +416,6 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
412 | else | 416 | else |
413 | cmd = NULL; | 417 | cmd = NULL; |
414 | 418 | ||
415 | /* warn if this is cmd response / notification and the uCode | ||
416 | * didn't set the SEQ_RX_FRAME for a frame that is | ||
417 | * uCode-originated | ||
418 | * If you saw this code after the second half of 2012, then | ||
419 | * please remove it | ||
420 | */ | ||
421 | WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false && | ||
422 | (!(pkt->hdr.sequence & SEQ_RX_FRAME)), | ||
423 | "reclaim is false, SEQ_RX_FRAME unset: %s\n", | ||
424 | get_cmd_string(pkt->hdr.cmd)); | ||
425 | |||
426 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); | 419 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); |
427 | 420 | ||
428 | /* | 421 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 14b0361d46ea..4900dfa59df7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | |||
@@ -1626,6 +1626,13 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
1626 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1626 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1627 | 1627 | ||
1628 | trans_pcie->cmd_queue = trans_cfg->cmd_queue; | 1628 | trans_pcie->cmd_queue = trans_cfg->cmd_queue; |
1629 | if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS)) | ||
1630 | trans_pcie->n_no_reclaim_cmds = 0; | ||
1631 | else | ||
1632 | trans_pcie->n_no_reclaim_cmds = trans_cfg->n_no_reclaim_cmds; | ||
1633 | if (trans_pcie->n_no_reclaim_cmds) | ||
1634 | memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds, | ||
1635 | trans_pcie->n_no_reclaim_cmds * sizeof(u8)); | ||
1629 | } | 1636 | } |
1630 | 1637 | ||
1631 | static void iwl_trans_pcie_free(struct iwl_trans *trans) | 1638 | static void iwl_trans_pcie_free(struct iwl_trans *trans) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 7d1990c7f658..95f3faf4e866 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -274,6 +274,8 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) | |||
274 | return p; | 274 | return p; |
275 | } | 275 | } |
276 | 276 | ||
277 | #define MAX_NO_RECLAIM_CMDS 6 | ||
278 | |||
277 | /** | 279 | /** |
278 | * struct iwl_trans_config - transport configuration | 280 | * struct iwl_trans_config - transport configuration |
279 | * | 281 | * |
@@ -281,10 +283,17 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) | |||
281 | * Must be set before any other call. | 283 | * Must be set before any other call. |
282 | * @cmd_queue: the index of the command queue. | 284 | * @cmd_queue: the index of the command queue. |
283 | * Must be set before start_fw. | 285 | * Must be set before start_fw. |
286 | * @no_reclaim_cmds: Some devices erroneously don't set the | ||
287 | * SEQ_RX_FRAME bit on some notifications, this is the | ||
288 | * list of such notifications to filter. Max length is | ||
289 | * %MAX_NO_RECLAIM_CMDS. | ||
290 | * @n_no_reclaim_cmds: # of commands in list | ||
284 | */ | 291 | */ |
285 | struct iwl_trans_config { | 292 | struct iwl_trans_config { |
286 | struct iwl_op_mode *op_mode; | 293 | struct iwl_op_mode *op_mode; |
287 | u8 cmd_queue; | 294 | u8 cmd_queue; |
295 | const u8 *no_reclaim_cmds; | ||
296 | int n_no_reclaim_cmds; | ||
288 | }; | 297 | }; |
289 | 298 | ||
290 | /** | 299 | /** |