aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-03-10 16:00:07 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-12 14:21:56 -0400
commitd663ee73f62903aed334eca25832a76c4a7e4c1c (patch)
tree3a8885ee9ddae0c6c18097f2530c42d221e433b0
parent10d8f31ebbd6ea9aa8d65d2f04ebef63225052de (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.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h9
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
1631static void iwl_trans_pcie_free(struct iwl_trans *trans) 1638static 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 */
285struct iwl_trans_config { 292struct 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/**