aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-08-23 04:46:33 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2010-08-27 11:27:29 -0400
commit13bb9483e190b95b04b22280ec9efa6b48469fd6 (patch)
treefdc39df48473db0ed02193eeb92d0e6a06a33ff8 /drivers
parent246ed355221076884d225f9d8a4c30a048be8162 (diff)
iwlwifi: prepare for PAN queue/fifo assignment
PAN ucode will require a different queue assignment, in particular queue 9 instead of 4 should be used for commands. This is required because the ucode will stop/start queues 4 and 8 depending on the PAN state, since queue 8 will be used for PAN multicast (after DTIM). Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-hw.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c34
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c2
13 files changed, 77 insertions, 46 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index a4a3194779d2..65b5834da28c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -226,6 +226,7 @@ struct iwl3945_eeprom {
226 226
227/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ 227/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
228#define IWL39_NUM_QUEUES 5 228#define IWL39_NUM_QUEUES 5
229#define IWL39_CMD_QUEUE_NUM 4
229 230
230#define IWL_DEFAULT_TX_RETRY 15 231#define IWL_DEFAULT_TX_RETRY 15
231 232
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index f4aa229986ca..f059b1dd4d41 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -273,7 +273,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
273 struct iwl_queue *q = &txq->q; 273 struct iwl_queue *q = &txq->q;
274 struct iwl_tx_info *tx_info; 274 struct iwl_tx_info *tx_info;
275 275
276 BUG_ON(txq_id == IWL_CMD_QUEUE_NUM); 276 BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM);
277 277
278 for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; 278 for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
279 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { 279 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
@@ -285,7 +285,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
285 } 285 }
286 286
287 if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && 287 if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
288 (txq_id != IWL_CMD_QUEUE_NUM) && 288 (txq_id != IWL39_CMD_QUEUE_NUM) &&
289 priv->mac80211_registered) 289 priv->mac80211_registered)
290 iwl_wake_queue(priv, txq_id); 290 iwl_wake_queue(priv, txq_id);
291} 291}
@@ -760,7 +760,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
760 data_retry_limit = IWL_DEFAULT_TX_RETRY; 760 data_retry_limit = IWL_DEFAULT_TX_RETRY;
761 tx_cmd->data_retry_limit = data_retry_limit; 761 tx_cmd->data_retry_limit = data_retry_limit;
762 762
763 if (tx_id >= IWL_CMD_QUEUE_NUM) 763 if (tx_id >= IWL39_CMD_QUEUE_NUM)
764 rts_retry_limit = 3; 764 rts_retry_limit = 3;
765 else 765 else
766 rts_retry_limit = 7; 766 rts_retry_limit = 7;
@@ -909,7 +909,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
909 909
910 /* Tx queue(s) */ 910 /* Tx queue(s) */
911 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { 911 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
912 slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? 912 slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ?
913 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; 913 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
914 rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, 914 rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
915 txq_id); 915 txq_id);
@@ -1072,7 +1072,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
1072 if (priv->txq) 1072 if (priv->txq)
1073 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; 1073 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
1074 txq_id++) 1074 txq_id++)
1075 if (txq_id == IWL_CMD_QUEUE_NUM) 1075 if (txq_id == IWL39_CMD_QUEUE_NUM)
1076 iwl_cmd_queue_free(priv); 1076 iwl_cmd_queue_free(priv);
1077 else 1077 else
1078 iwl_tx_queue_free(priv, txq_id); 1078 iwl_tx_queue_free(priv, txq_id);
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 82f32305f50e..cda389c3b025 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -576,7 +576,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
576 /* Activate all Tx DMA/FIFO channels */ 576 /* Activate all Tx DMA/FIFO channels */
577 priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6)); 577 priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6));
578 578
579 iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); 579 iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0);
580 580
581 /* make sure all queue are not stopped */ 581 /* make sure all queue are not stopped */
582 memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); 582 memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
@@ -587,6 +587,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
587 priv->txq_ctx_active_msk = 0; 587 priv->txq_ctx_active_msk = 0;
588 /* Map each Tx/cmd queue to its corresponding fifo */ 588 /* Map each Tx/cmd queue to its corresponding fifo */
589 BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7); 589 BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
590
590 for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { 591 for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
591 int ac = default_queue_to_tx_fifo[i]; 592 int ac = default_queue_to_tx_fifo[i];
592 593
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 531a7dc3dc72..f919977d5632 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -1479,7 +1479,7 @@ int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv)
1479 1479
1480 /* waiting for all the tx frames complete might take a while */ 1480 /* waiting for all the tx frames complete might take a while */
1481 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { 1481 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
1482 if (cnt == IWL_CMD_QUEUE_NUM) 1482 if (cnt == priv->cmd_queue)
1483 continue; 1483 continue;
1484 txq = &priv->txq[cnt]; 1484 txq = &priv->txq[cnt];
1485 q = &txq->q; 1485 q = &txq->q;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index a51a7cfa5a14..88b7bbfb1f91 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -118,7 +118,7 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
118 118
119 WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); 119 WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
120 120
121 if (txq_id != IWL_CMD_QUEUE_NUM) { 121 if (txq_id != priv->cmd_queue) {
122 sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; 122 sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
123 sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; 123 sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
124 124
@@ -155,7 +155,7 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
155 155
156 WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); 156 WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
157 157
158 if (txq_id != IWL_CMD_QUEUE_NUM) 158 if (txq_id != priv->cmd_queue)
159 sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; 159 sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
160 160
161 bc_ent = cpu_to_le16(1 | (sta_id << 12)); 161 bc_ent = cpu_to_le16(1 | (sta_id << 12));
@@ -825,7 +825,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv)
825 /* Tx queues */ 825 /* Tx queues */
826 if (priv->txq) { 826 if (priv->txq) {
827 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) 827 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
828 if (txq_id == IWL_CMD_QUEUE_NUM) 828 if (txq_id == priv->cmd_queue)
829 iwl_cmd_queue_free(priv); 829 iwl_cmd_queue_free(priv);
830 else 830 else
831 iwl_tx_queue_free(priv, txq_id); 831 iwl_tx_queue_free(priv, txq_id);
@@ -882,9 +882,9 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
882 882
883 spin_unlock_irqrestore(&priv->lock, flags); 883 spin_unlock_irqrestore(&priv->lock, flags);
884 884
885 /* Alloc and init all Tx queues, including the command queue (#4) */ 885 /* Alloc and init all Tx queues, including the command queue (#4/#9) */
886 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { 886 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
887 slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? 887 slots_num = (txq_id == priv->cmd_queue) ?
888 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; 888 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
889 ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, 889 ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
890 txq_id); 890 txq_id);
@@ -922,7 +922,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
922 922
923 /* Alloc and init all Tx queues, including the command queue (#4) */ 923 /* Alloc and init all Tx queues, including the command queue (#4) */
924 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { 924 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
925 slots_num = txq_id == IWL_CMD_QUEUE_NUM ? 925 slots_num = txq_id == priv->cmd_queue ?
926 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; 926 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
927 iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); 927 iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
928 } 928 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index f2499e1f2047..a9ea7a1fef02 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -52,6 +52,19 @@ static const s8 iwlagn_default_queue_to_tx_fifo[] = {
52 IWL_TX_FIFO_UNUSED, 52 IWL_TX_FIFO_UNUSED,
53}; 53};
54 54
55static const s8 iwlagn_ipan_queue_to_tx_fifo[] = {
56 IWL_TX_FIFO_VO,
57 IWL_TX_FIFO_VI,
58 IWL_TX_FIFO_BE,
59 IWL_TX_FIFO_BK,
60 IWL_TX_FIFO_UNUSED, /* FIXME */
61 IWL_TX_FIFO_UNUSED, /* FIXME */
62 IWL_TX_FIFO_UNUSED, /* FIXME */
63 IWL_TX_FIFO_UNUSED, /* FIXME */
64 IWL_TX_FIFO_UNUSED, /* FIXME */
65 IWLAGN_CMD_FIFO_NUM,
66};
67
55static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { 68static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
56 {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, 69 {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
57 0, COEX_UNASSOC_IDLE_FLAGS}, 70 0, COEX_UNASSOC_IDLE_FLAGS},
@@ -376,6 +389,7 @@ static void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
376 389
377int iwlagn_alive_notify(struct iwl_priv *priv) 390int iwlagn_alive_notify(struct iwl_priv *priv)
378{ 391{
392 const s8 *queues;
379 u32 a; 393 u32 a;
380 unsigned long flags; 394 unsigned long flags;
381 int i, chan; 395 int i, chan;
@@ -410,7 +424,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
410 reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); 424 reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
411 425
412 iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, 426 iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL,
413 IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); 427 IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv));
414 iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0); 428 iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
415 429
416 /* initiate the queues */ 430 /* initiate the queues */
@@ -436,7 +450,13 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
436 /* Activate all Tx DMA/FIFO channels */ 450 /* Activate all Tx DMA/FIFO channels */
437 priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); 451 priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
438 452
439 iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); 453 /* map queues to FIFOs */
454 if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
455 queues = iwlagn_ipan_queue_to_tx_fifo;
456 else
457 queues = iwlagn_default_queue_to_tx_fifo;
458
459 iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0);
440 460
441 /* make sure all queue are not stopped */ 461 /* make sure all queue are not stopped */
442 memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); 462 memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
@@ -445,11 +465,12 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
445 465
446 /* reset to 0 to enable all the queue first */ 466 /* reset to 0 to enable all the queue first */
447 priv->txq_ctx_active_msk = 0; 467 priv->txq_ctx_active_msk = 0;
448 /* map qos queues to fifos one-to-one */ 468
449 BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); 469 BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
470 BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
450 471
451 for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) { 472 for (i = 0; i < 10; i++) {
452 int ac = iwlagn_default_queue_to_tx_fifo[i]; 473 int ac = queues[i];
453 474
454 iwl_txq_ctx_activate(priv, i); 475 iwl_txq_ctx_activate(priv, i);
455 476
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index e073069a44c2..cfc8e8de8798 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3011,6 +3011,9 @@ static int __iwl_up(struct iwl_priv *priv)
3011 3011
3012 iwl_write32(priv, CSR_INT, 0xFFFFFFFF); 3012 iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
3013 3013
3014 /* must be initialised before iwl_hw_nic_init */
3015 priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
3016
3014 ret = iwlagn_hw_nic_init(priv); 3017 ret = iwlagn_hw_nic_init(priv);
3015 if (ret) { 3018 if (ret) {
3016 IWL_ERR(priv, "Unable to init nic\n"); 3019 IWL_ERR(priv, "Unable to init nic\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index cc88401960e4..f6aa5ce478b4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2757,14 +2757,14 @@ void iwl_bg_monitor_recover(unsigned long data)
2757 return; 2757 return;
2758 2758
2759 /* monitor and check for stuck cmd queue */ 2759 /* monitor and check for stuck cmd queue */
2760 if (iwl_check_stuck_queue(priv, IWL_CMD_QUEUE_NUM)) 2760 if (iwl_check_stuck_queue(priv, priv->cmd_queue))
2761 return; 2761 return;
2762 2762
2763 /* monitor and check for other stuck queues */ 2763 /* monitor and check for other stuck queues */
2764 if (iwl_is_any_associated(priv)) { 2764 if (iwl_is_any_associated(priv)) {
2765 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { 2765 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
2766 /* skip as we already checked the command queue */ 2766 /* skip as we already checked the command queue */
2767 if (cnt == IWL_CMD_QUEUE_NUM) 2767 if (cnt == priv->cmd_queue)
2768 continue; 2768 continue;
2769 if (iwl_check_stuck_queue(priv, cnt)) 2769 if (iwl_check_stuck_queue(priv, cnt))
2770 return; 2770 return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 6b188926014b..7cafb26a5f52 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -265,11 +265,10 @@ struct iwl_channel_info {
265#define IWL_MIN_NUM_QUEUES 10 265#define IWL_MIN_NUM_QUEUES 10
266 266
267/* 267/*
268 * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00, 268 * Command queue depends on iPAN support.
269 * the driver maps it into the appropriate device FIFO for the
270 * uCode.
271 */ 269 */
272#define IWL_CMD_QUEUE_NUM 4 270#define IWL_DEFAULT_CMD_QUEUE_NUM 4
271#define IWL_IPAN_CMD_QUEUE_NUM 9
273 272
274/* Power management (not Tx power) structures */ 273/* Power management (not Tx power) structures */
275 274
@@ -1197,6 +1196,9 @@ struct iwl_priv {
1197 /* microcode/device supports multiple contexts */ 1196 /* microcode/device supports multiple contexts */
1198 u8 valid_contexts; 1197 u8 valid_contexts;
1199 1198
1199 /* command queue number */
1200 u8 cmd_queue;
1201
1200 /* EEPROM MAC addresses */ 1202 /* EEPROM MAC addresses */
1201 struct mac_address addresses[2]; 1203 struct mac_address addresses[2];
1202 1204
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 1f15b3aa8478..9fb2035e4eca 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -232,7 +232,7 @@ cancel:
232 * in later, it will possibly set an invalid 232 * in later, it will possibly set an invalid
233 * address (cmd->meta.source). 233 * address (cmd->meta.source).
234 */ 234 */
235 priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_idx].flags &= 235 priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
236 ~CMD_WANT_SKB; 236 ~CMD_WANT_SKB;
237 } 237 }
238fail: 238fail:
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index b1f101caf19d..5469655646ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -306,7 +306,7 @@
306 * at a time, until receiving ACK from receiving station, or reaching 306 * at a time, until receiving ACK from receiving station, or reaching
307 * retry limit and giving up. 307 * retry limit and giving up.
308 * 308 *
309 * The command queue (#4) must use this mode! 309 * The command queue (#4/#9) must use this mode!
310 * This mode does not require use of the Byte Count table in host DRAM. 310 * This mode does not require use of the Byte Count table in host DRAM.
311 * 311 *
312 * Driver controls scheduler operation via 3 means: 312 * Driver controls scheduler operation via 3 means:
@@ -322,7 +322,7 @@
322 * (1024 bytes for each queue). 322 * (1024 bytes for each queue).
323 * 323 *
324 * After receiving "Alive" response from uCode, driver must initialize 324 * After receiving "Alive" response from uCode, driver must initialize
325 * the scheduler (especially for queue #4, the command queue, otherwise 325 * the scheduler (especially for queue #4/#9, the command queue, otherwise
326 * the driver can't issue commands!): 326 * the driver can't issue commands!):
327 */ 327 */
328 328
@@ -555,8 +555,9 @@
555#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ 555#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
556 ((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) 556 ((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
557 557
558#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\ 558#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \
559 (~(1<<IWL_CMD_QUEUE_NUM))) 559 (((1<<(priv)->hw_params.max_txq_num) - 1) &\
560 (~(1<<(priv)->cmd_queue)))
560 561
561#define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00) 562#define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00)
562 563
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index c308dab14673..347d3dc6a015 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -134,7 +134,7 @@ EXPORT_SYMBOL(iwl_tx_queue_free);
134 */ 134 */
135void iwl_cmd_queue_free(struct iwl_priv *priv) 135void iwl_cmd_queue_free(struct iwl_priv *priv)
136{ 136{
137 struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; 137 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
138 struct iwl_queue *q = &txq->q; 138 struct iwl_queue *q = &txq->q;
139 struct device *dev = &priv->pci_dev->dev; 139 struct device *dev = &priv->pci_dev->dev;
140 int i; 140 int i;
@@ -271,7 +271,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
271 271
272 /* Driver private data, only for Tx (not command) queues, 272 /* Driver private data, only for Tx (not command) queues,
273 * not shared with device. */ 273 * not shared with device. */
274 if (id != IWL_CMD_QUEUE_NUM) { 274 if (id != priv->cmd_queue) {
275 txq->txb = kzalloc(sizeof(txq->txb[0]) * 275 txq->txb = kzalloc(sizeof(txq->txb[0]) *
276 TFD_QUEUE_SIZE_MAX, GFP_KERNEL); 276 TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
277 if (!txq->txb) { 277 if (!txq->txb) {
@@ -314,13 +314,13 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
314 314
315 /* 315 /*
316 * Alloc buffer array for commands (Tx or other types of commands). 316 * Alloc buffer array for commands (Tx or other types of commands).
317 * For the command queue (#4), allocate command space + one big 317 * For the command queue (#4/#9), allocate command space + one big
318 * command for scan, since scan command is very huge; the system will 318 * command for scan, since scan command is very huge; the system will
319 * not have two scans at the same time, so only one is needed. 319 * not have two scans at the same time, so only one is needed.
320 * For normal Tx queues (all other queues), no super-size command 320 * For normal Tx queues (all other queues), no super-size command
321 * space is needed. 321 * space is needed.
322 */ 322 */
323 if (txq_id == IWL_CMD_QUEUE_NUM) 323 if (txq_id == priv->cmd_queue)
324 actual_slots++; 324 actual_slots++;
325 325
326 txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots, 326 txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
@@ -355,7 +355,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
355 * need an swq_id so don't set one to catch errors, all others can 355 * need an swq_id so don't set one to catch errors, all others can
356 * be set up to the identity mapping. 356 * be set up to the identity mapping.
357 */ 357 */
358 if (txq_id != IWL_CMD_QUEUE_NUM) 358 if (txq_id != priv->cmd_queue)
359 txq->swq_id = txq_id; 359 txq->swq_id = txq_id;
360 360
361 /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise 361 /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
@@ -385,7 +385,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
385{ 385{
386 int actual_slots = slots_num; 386 int actual_slots = slots_num;
387 387
388 if (txq_id == IWL_CMD_QUEUE_NUM) 388 if (txq_id == priv->cmd_queue)
389 actual_slots++; 389 actual_slots++;
390 390
391 memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); 391 memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
@@ -413,7 +413,7 @@ EXPORT_SYMBOL(iwl_tx_queue_reset);
413 */ 413 */
414int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) 414int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
415{ 415{
416 struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; 416 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
417 struct iwl_queue *q = &txq->q; 417 struct iwl_queue *q = &txq->q;
418 struct iwl_device_cmd *out_cmd; 418 struct iwl_device_cmd *out_cmd;
419 struct iwl_cmd_meta *out_meta; 419 struct iwl_cmd_meta *out_meta;
@@ -483,7 +483,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
483 * information */ 483 * information */
484 484
485 out_cmd->hdr.flags = 0; 485 out_cmd->hdr.flags = 0;
486 out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) | 486 out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
487 INDEX_TO_SEQ(q->write_ptr)); 487 INDEX_TO_SEQ(q->write_ptr));
488 if (cmd->flags & CMD_SIZE_HUGE) 488 if (cmd->flags & CMD_SIZE_HUGE)
489 out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; 489 out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
@@ -500,15 +500,15 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
500 get_cmd_string(out_cmd->hdr.cmd), 500 get_cmd_string(out_cmd->hdr.cmd),
501 out_cmd->hdr.cmd, 501 out_cmd->hdr.cmd,
502 le16_to_cpu(out_cmd->hdr.sequence), fix_size, 502 le16_to_cpu(out_cmd->hdr.sequence), fix_size,
503 q->write_ptr, idx, IWL_CMD_QUEUE_NUM); 503 q->write_ptr, idx, priv->cmd_queue);
504 break; 504 break;
505 default: 505 default:
506 IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " 506 IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
507 "%d bytes at %d[%d]:%d\n", 507 "%d bytes at %d[%d]:%d\n",
508 get_cmd_string(out_cmd->hdr.cmd), 508 get_cmd_string(out_cmd->hdr.cmd),
509 out_cmd->hdr.cmd, 509 out_cmd->hdr.cmd,
510 le16_to_cpu(out_cmd->hdr.sequence), fix_size, 510 le16_to_cpu(out_cmd->hdr.sequence), fix_size,
511 q->write_ptr, idx, IWL_CMD_QUEUE_NUM); 511 q->write_ptr, idx, priv->cmd_queue);
512 } 512 }
513#endif 513#endif
514 txq->need_update = 1; 514 txq->need_update = 1;
@@ -587,16 +587,16 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
587 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); 587 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
588 struct iwl_device_cmd *cmd; 588 struct iwl_device_cmd *cmd;
589 struct iwl_cmd_meta *meta; 589 struct iwl_cmd_meta *meta;
590 struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; 590 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
591 591
592 /* If a Tx command is being handled and it isn't in the actual 592 /* If a Tx command is being handled and it isn't in the actual
593 * command queue then there a command routing bug has been introduced 593 * command queue then there a command routing bug has been introduced
594 * in the queue management code. */ 594 * in the queue management code. */
595 if (WARN(txq_id != IWL_CMD_QUEUE_NUM, 595 if (WARN(txq_id != priv->cmd_queue,
596 "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n", 596 "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
597 txq_id, sequence, 597 txq_id, priv->cmd_queue, sequence,
598 priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr, 598 priv->txq[priv->cmd_queue].q.read_ptr,
599 priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) { 599 priv->txq[priv->cmd_queue].q.write_ptr)) {
600 iwl_print_hex_error(priv, pkt, 32); 600 iwl_print_hex_error(priv, pkt, 32);
601 return; 601 return;
602 } 602 }
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 234d6b430fcf..02e0a9bbad16 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -4001,6 +4001,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
4001 priv = hw->priv; 4001 priv = hw->priv;
4002 SET_IEEE80211_DEV(hw, &pdev->dev); 4002 SET_IEEE80211_DEV(hw, &pdev->dev);
4003 4003
4004 priv->cmd_queue = IWL39_CMD_QUEUE_NUM;
4005
4004 /* 3945 has only one valid context */ 4006 /* 3945 has only one valid context */
4005 priv->valid_contexts = BIT(IWL_RXON_CTX_BSS); 4007 priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
4006 4008