aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-24 14:13:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-27 15:24:21 -0400
commitc2acea8e9b86ba5a5469ff477445676a223af4e2 (patch)
tree3c4705b13dd5c85817a1132a17743757135b7047 /drivers/net/wireless/iwlwifi/iwl-tx.c
parentfbf3a2af3834e8e93e9c2876de62c5b49988e352 (diff)
iwlwifi: fix up command sending
The current command sending in iwlwifi is a bit of a mess: 1) there is a struct, iwl_cmd, that contains both driver and device data in a single packed structure -- this is very confusing 2) the on-stack data and the command metadata share a structure by embedding the latter in the former, which is also rather confusing because it leads to weird unions and similarly odd constructs 3) each txq always has enough space for 256 commands, even if only 32 end up being used This patch fixes these things: 1) rename iwl_cmd to iwl_device_cmd and keep track of command metadata and device command separately, in two arrays in each tx queue 2) remove the 'meta' member from iwl_host_cmd and only put in the required members 3) allocate the cmd/meta arrays separately instead of embedding them into the txq structure Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-tx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c96
1 files changed, 59 insertions, 37 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 0912987af603..51ddbab63c23 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -141,7 +141,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
141 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) 141 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
142 priv->cfg->ops->lib->txq_free_tfd(priv, txq); 142 priv->cfg->ops->lib->txq_free_tfd(priv, txq);
143 143
144 len = sizeof(struct iwl_cmd) * q->n_window; 144 len = sizeof(struct iwl_device_cmd) * q->n_window;
145 145
146 /* De-alloc array of command/tx buffers */ 146 /* De-alloc array of command/tx buffers */
147 for (i = 0; i < TFD_TX_CMD_SLOTS; i++) 147 for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
@@ -156,6 +156,12 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
156 kfree(txq->txb); 156 kfree(txq->txb);
157 txq->txb = NULL; 157 txq->txb = NULL;
158 158
159 /* deallocate arrays */
160 kfree(txq->cmd);
161 kfree(txq->meta);
162 txq->cmd = NULL;
163 txq->meta = NULL;
164
159 /* 0-fill queue descriptor structure */ 165 /* 0-fill queue descriptor structure */
160 memset(txq, 0, sizeof(*txq)); 166 memset(txq, 0, sizeof(*txq));
161} 167}
@@ -179,7 +185,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
179 if (q->n_bd == 0) 185 if (q->n_bd == 0)
180 return; 186 return;
181 187
182 len = sizeof(struct iwl_cmd) * q->n_window; 188 len = sizeof(struct iwl_device_cmd) * q->n_window;
183 len += IWL_MAX_SCAN_SIZE; 189 len += IWL_MAX_SCAN_SIZE;
184 190
185 /* De-alloc array of command/tx buffers */ 191 /* De-alloc array of command/tx buffers */
@@ -318,6 +324,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
318{ 324{
319 int i, len; 325 int i, len;
320 int ret; 326 int ret;
327 int actual_slots = slots_num;
321 328
322 /* 329 /*
323 * Alloc buffer array for commands (Tx or other types of commands). 330 * Alloc buffer array for commands (Tx or other types of commands).
@@ -327,14 +334,22 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
327 * For normal Tx queues (all other queues), no super-size command 334 * For normal Tx queues (all other queues), no super-size command
328 * space is needed. 335 * space is needed.
329 */ 336 */
330 len = sizeof(struct iwl_cmd); 337 if (txq_id == IWL_CMD_QUEUE_NUM)
331 for (i = 0; i <= slots_num; i++) { 338 actual_slots++;
332 if (i == slots_num) { 339
333 if (txq_id == IWL_CMD_QUEUE_NUM) 340 txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
334 len += IWL_MAX_SCAN_SIZE; 341 GFP_KERNEL);
335 else 342 txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots,
336 continue; 343 GFP_KERNEL);
337 } 344
345 if (!txq->meta || !txq->cmd)
346 goto out_free_arrays;
347
348 len = sizeof(struct iwl_device_cmd);
349 for (i = 0; i < actual_slots; i++) {
350 /* only happens for cmd queue */
351 if (i == slots_num)
352 len += IWL_MAX_SCAN_SIZE;
338 353
339 txq->cmd[i] = kmalloc(len, GFP_KERNEL); 354 txq->cmd[i] = kmalloc(len, GFP_KERNEL);
340 if (!txq->cmd[i]) 355 if (!txq->cmd[i])
@@ -364,15 +379,12 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
364 379
365 return 0; 380 return 0;
366err: 381err:
367 for (i = 0; i < slots_num; i++) { 382 for (i = 0; i < actual_slots; i++)
368 kfree(txq->cmd[i]); 383 kfree(txq->cmd[i]);
369 txq->cmd[i] = NULL; 384out_free_arrays:
370 } 385 kfree(txq->meta);
386 kfree(txq->cmd);
371 387
372 if (txq_id == IWL_CMD_QUEUE_NUM) {
373 kfree(txq->cmd[slots_num]);
374 txq->cmd[slots_num] = NULL;
375 }
376 return -ENOMEM; 388 return -ENOMEM;
377} 389}
378EXPORT_SYMBOL(iwl_tx_queue_init); 390EXPORT_SYMBOL(iwl_tx_queue_init);
@@ -673,7 +685,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
673 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 685 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
674 struct iwl_tx_queue *txq; 686 struct iwl_tx_queue *txq;
675 struct iwl_queue *q; 687 struct iwl_queue *q;
676 struct iwl_cmd *out_cmd; 688 struct iwl_device_cmd *out_cmd;
689 struct iwl_cmd_meta *out_meta;
677 struct iwl_tx_cmd *tx_cmd; 690 struct iwl_tx_cmd *tx_cmd;
678 int swq_id, txq_id; 691 int swq_id, txq_id;
679 dma_addr_t phys_addr; 692 dma_addr_t phys_addr;
@@ -766,6 +779,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
766 779
767 /* Set up first empty entry in queue's array of Tx/cmd buffers */ 780 /* Set up first empty entry in queue's array of Tx/cmd buffers */
768 out_cmd = txq->cmd[q->write_ptr]; 781 out_cmd = txq->cmd[q->write_ptr];
782 out_meta = &txq->meta[q->write_ptr];
769 tx_cmd = &out_cmd->cmd.tx; 783 tx_cmd = &out_cmd->cmd.tx;
770 memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); 784 memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
771 memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); 785 memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
@@ -828,8 +842,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
828 txcmd_phys = pci_map_single(priv->pci_dev, 842 txcmd_phys = pci_map_single(priv->pci_dev,
829 &out_cmd->hdr, len, 843 &out_cmd->hdr, len,
830 PCI_DMA_BIDIRECTIONAL); 844 PCI_DMA_BIDIRECTIONAL);
831 pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys); 845 pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
832 pci_unmap_len_set(&out_cmd->meta, len, len); 846 pci_unmap_len_set(out_meta, len, len);
833 /* Add buffer containing Tx command and MAC(!) header to TFD's 847 /* Add buffer containing Tx command and MAC(!) header to TFD's
834 * first entry */ 848 * first entry */
835 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, 849 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
@@ -923,7 +937,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
923{ 937{
924 struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; 938 struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
925 struct iwl_queue *q = &txq->q; 939 struct iwl_queue *q = &txq->q;
926 struct iwl_cmd *out_cmd; 940 struct iwl_device_cmd *out_cmd;
941 struct iwl_cmd_meta *out_meta;
927 dma_addr_t phys_addr; 942 dma_addr_t phys_addr;
928 unsigned long flags; 943 unsigned long flags;
929 int len, ret; 944 int len, ret;
@@ -937,25 +952,31 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
937 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then 952 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
938 * we will need to increase the size of the TFD entries */ 953 * we will need to increase the size of the TFD entries */
939 BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && 954 BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
940 !(cmd->meta.flags & CMD_SIZE_HUGE)); 955 !(cmd->flags & CMD_SIZE_HUGE));
941 956
942 if (iwl_is_rfkill(priv)) { 957 if (iwl_is_rfkill(priv)) {
943 IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n"); 958 IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n");
944 return -EIO; 959 return -EIO;
945 } 960 }
946 961
947 if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { 962 if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
948 IWL_ERR(priv, "No space for Tx\n"); 963 IWL_ERR(priv, "No space for Tx\n");
949 return -ENOSPC; 964 return -ENOSPC;
950 } 965 }
951 966
952 spin_lock_irqsave(&priv->hcmd_lock, flags); 967 spin_lock_irqsave(&priv->hcmd_lock, flags);
953 968
954 idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); 969 idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
955 out_cmd = txq->cmd[idx]; 970 out_cmd = txq->cmd[idx];
971 out_meta = &txq->meta[idx];
972
973 out_meta->flags = cmd->flags;
974 if (cmd->flags & CMD_WANT_SKB)
975 out_meta->source = cmd;
976 if (cmd->flags & CMD_ASYNC)
977 out_meta->callback = cmd->callback;
956 978
957 out_cmd->hdr.cmd = cmd->id; 979 out_cmd->hdr.cmd = cmd->id;
958 memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
959 memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len); 980 memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
960 981
961 /* At this point, the out_cmd now has all of the incoming cmd 982 /* At this point, the out_cmd now has all of the incoming cmd
@@ -964,9 +985,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
964 out_cmd->hdr.flags = 0; 985 out_cmd->hdr.flags = 0;
965 out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) | 986 out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
966 INDEX_TO_SEQ(q->write_ptr)); 987 INDEX_TO_SEQ(q->write_ptr));
967 if (out_cmd->meta.flags & CMD_SIZE_HUGE) 988 if (cmd->flags & CMD_SIZE_HUGE)
968 out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; 989 out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
969 len = sizeof(struct iwl_cmd) - sizeof(struct iwl_cmd_meta); 990 len = sizeof(struct iwl_device_cmd);
970 len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0; 991 len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0;
971 992
972 993
@@ -998,8 +1019,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
998 1019
999 phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, 1020 phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
1000 fix_size, PCI_DMA_BIDIRECTIONAL); 1021 fix_size, PCI_DMA_BIDIRECTIONAL);
1001 pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr); 1022 pci_unmap_addr_set(out_meta, mapping, phys_addr);
1002 pci_unmap_len_set(&out_cmd->meta, len, fix_size); 1023 pci_unmap_len_set(out_meta, len, fix_size);
1003 1024
1004 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, 1025 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
1005 phys_addr, fix_size, 1, 1026 phys_addr, fix_size, 1,
@@ -1068,8 +1089,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
1068 } 1089 }
1069 1090
1070 pci_unmap_single(priv->pci_dev, 1091 pci_unmap_single(priv->pci_dev,
1071 pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping), 1092 pci_unmap_addr(&txq->meta[cmd_idx], mapping),
1072 pci_unmap_len(&txq->cmd[cmd_idx]->meta, len), 1093 pci_unmap_len(&txq->meta[cmd_idx], len),
1073 PCI_DMA_BIDIRECTIONAL); 1094 PCI_DMA_BIDIRECTIONAL);
1074 1095
1075 for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; 1096 for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
@@ -1100,7 +1121,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1100 int index = SEQ_TO_INDEX(sequence); 1121 int index = SEQ_TO_INDEX(sequence);
1101 int cmd_index; 1122 int cmd_index;
1102 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); 1123 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
1103 struct iwl_cmd *cmd; 1124 struct iwl_device_cmd *cmd;
1125 struct iwl_cmd_meta *meta;
1104 1126
1105 /* If a Tx command is being handled and it isn't in the actual 1127 /* If a Tx command is being handled and it isn't in the actual
1106 * command queue then there a command routing bug has been introduced 1128 * command queue then there a command routing bug has been introduced
@@ -1116,18 +1138,18 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1116 1138
1117 cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); 1139 cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
1118 cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; 1140 cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
1141 meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index];
1119 1142
1120 /* Input error checking is done when commands are added to queue. */ 1143 /* Input error checking is done when commands are added to queue. */
1121 if (cmd->meta.flags & CMD_WANT_SKB) { 1144 if (meta->flags & CMD_WANT_SKB) {
1122 cmd->meta.source->u.skb = rxb->skb; 1145 meta->source->reply_skb = rxb->skb;
1123 rxb->skb = NULL; 1146 rxb->skb = NULL;
1124 } else if (cmd->meta.u.callback && 1147 } else if (meta->callback && !meta->callback(priv, cmd, rxb->skb))
1125 !cmd->meta.u.callback(priv, cmd, rxb->skb))
1126 rxb->skb = NULL; 1148 rxb->skb = NULL;
1127 1149
1128 iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); 1150 iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
1129 1151
1130 if (!(cmd->meta.flags & CMD_ASYNC)) { 1152 if (!(meta->flags & CMD_ASYNC)) {
1131 clear_bit(STATUS_HCMD_ACTIVE, &priv->status); 1153 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
1132 wake_up_interruptible(&priv->wait_command_queue); 1154 wake_up_interruptible(&priv->wait_command_queue);
1133 } 1155 }