aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c48
1 files changed, 45 insertions, 3 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 8c12311dbb0a..6aa309032f4e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -193,10 +193,34 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
193 struct iwl_queue *q = &txq->q; 193 struct iwl_queue *q = &txq->q;
194 struct device *dev = &priv->pci_dev->dev; 194 struct device *dev = &priv->pci_dev->dev;
195 int i; 195 int i;
196 bool huge = false;
196 197
197 if (q->n_bd == 0) 198 if (q->n_bd == 0)
198 return; 199 return;
199 200
201 for (; q->read_ptr != q->write_ptr;
202 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
203 /* we have no way to tell if it is a huge cmd ATM */
204 i = get_cmd_index(q, q->read_ptr, 0);
205
206 if (txq->meta[i].flags & CMD_SIZE_HUGE) {
207 huge = true;
208 continue;
209 }
210
211 pci_unmap_single(priv->pci_dev,
212 pci_unmap_addr(&txq->meta[i], mapping),
213 pci_unmap_len(&txq->meta[i], len),
214 PCI_DMA_BIDIRECTIONAL);
215 }
216 if (huge) {
217 i = q->n_window;
218 pci_unmap_single(priv->pci_dev,
219 pci_unmap_addr(&txq->meta[i], mapping),
220 pci_unmap_len(&txq->meta[i], len),
221 PCI_DMA_BIDIRECTIONAL);
222 }
223
200 /* De-alloc array of command/tx buffers */ 224 /* De-alloc array of command/tx buffers */
201 for (i = 0; i <= TFD_CMD_SLOTS; i++) 225 for (i = 0; i <= TFD_CMD_SLOTS; i++)
202 kfree(txq->cmd[i]); 226 kfree(txq->cmd[i]);
@@ -1049,6 +1073,14 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
1049 1073
1050 spin_lock_irqsave(&priv->hcmd_lock, flags); 1074 spin_lock_irqsave(&priv->hcmd_lock, flags);
1051 1075
1076 /* If this is a huge cmd, mark the huge flag also on the meta.flags
1077 * of the _original_ cmd. This is used for DMA mapping clean up.
1078 */
1079 if (cmd->flags & CMD_SIZE_HUGE) {
1080 idx = get_cmd_index(q, q->write_ptr, 0);
1081 txq->meta[idx].flags = CMD_SIZE_HUGE;
1082 }
1083
1052 idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); 1084 idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
1053 out_cmd = txq->cmd[idx]; 1085 out_cmd = txq->cmd[idx];
1054 out_meta = &txq->meta[idx]; 1086 out_meta = &txq->meta[idx];
@@ -1226,6 +1258,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1226 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); 1258 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
1227 struct iwl_device_cmd *cmd; 1259 struct iwl_device_cmd *cmd;
1228 struct iwl_cmd_meta *meta; 1260 struct iwl_cmd_meta *meta;
1261 struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
1229 1262
1230 /* If a Tx command is being handled and it isn't in the actual 1263 /* If a Tx command is being handled and it isn't in the actual
1231 * command queue then there a command routing bug has been introduced 1264 * command queue then there a command routing bug has been introduced
@@ -1239,9 +1272,17 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1239 return; 1272 return;
1240 } 1273 }
1241 1274
1242 cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); 1275 /* If this is a huge cmd, clear the huge flag on the meta.flags
1243 cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; 1276 * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap
1244 meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index]; 1277 * the DMA buffer for the scan (huge) command.
1278 */
1279 if (huge) {
1280 cmd_index = get_cmd_index(&txq->q, index, 0);
1281 txq->meta[cmd_index].flags = 0;
1282 }
1283 cmd_index = get_cmd_index(&txq->q, index, huge);
1284 cmd = txq->cmd[cmd_index];
1285 meta = &txq->meta[cmd_index];
1245 1286
1246 pci_unmap_single(priv->pci_dev, 1287 pci_unmap_single(priv->pci_dev,
1247 pci_unmap_addr(meta, mapping), 1288 pci_unmap_addr(meta, mapping),
@@ -1263,6 +1304,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1263 get_cmd_string(cmd->hdr.cmd)); 1304 get_cmd_string(cmd->hdr.cmd));
1264 wake_up_interruptible(&priv->wait_command_queue); 1305 wake_up_interruptible(&priv->wait_command_queue);
1265 } 1306 }
1307 meta->flags = 0;
1266} 1308}
1267EXPORT_SYMBOL(iwl_tx_cmd_complete); 1309EXPORT_SYMBOL(iwl_tx_cmd_complete);
1268 1310