diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-04-08 13:34:54 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-08 13:34:54 -0400 |
commit | 0f2df9eac70423838a1f8d410fd3899ddd88317b (patch) | |
tree | 0617f723320d83eca5cef9c964c001014e74213f /drivers/net/wireless/iwlwifi/iwl-tx.c | |
parent | 8c11e4ab09ffb975a89802dde0e9aa52a53b8aa5 (diff) | |
parent | 1144601118507f8b3b676a9a392584d216d3f2cc (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into merge
Conflicts:
Documentation/feature-removal-schedule.txt
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-tx.c
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 65090d386a53..a631afef5e33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -83,7 +83,7 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv, | |||
83 | if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) | 83 | if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) |
84 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | 84 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; |
85 | else { | 85 | else { |
86 | IWL_ERR(priv, "free more than tfds_in_queue (%u:%d)\n", | 86 | IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", |
87 | priv->stations[sta_id].tid[tid].tfds_in_queue, | 87 | priv->stations[sta_id].tid[tid].tfds_in_queue, |
88 | freed); | 88 | freed); |
89 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; | 89 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; |
@@ -152,10 +152,34 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
152 | struct iwl_queue *q = &txq->q; | 152 | struct iwl_queue *q = &txq->q; |
153 | struct device *dev = &priv->pci_dev->dev; | 153 | struct device *dev = &priv->pci_dev->dev; |
154 | int i; | 154 | int i; |
155 | bool huge = false; | ||
155 | 156 | ||
156 | if (q->n_bd == 0) | 157 | if (q->n_bd == 0) |
157 | return; | 158 | return; |
158 | 159 | ||
160 | for (; q->read_ptr != q->write_ptr; | ||
161 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
162 | /* we have no way to tell if it is a huge cmd ATM */ | ||
163 | i = get_cmd_index(q, q->read_ptr, 0); | ||
164 | |||
165 | if (txq->meta[i].flags & CMD_SIZE_HUGE) { | ||
166 | huge = true; | ||
167 | continue; | ||
168 | } | ||
169 | |||
170 | pci_unmap_single(priv->pci_dev, | ||
171 | pci_unmap_addr(&txq->meta[i], mapping), | ||
172 | pci_unmap_len(&txq->meta[i], len), | ||
173 | PCI_DMA_BIDIRECTIONAL); | ||
174 | } | ||
175 | if (huge) { | ||
176 | i = q->n_window; | ||
177 | pci_unmap_single(priv->pci_dev, | ||
178 | pci_unmap_addr(&txq->meta[i], mapping), | ||
179 | pci_unmap_len(&txq->meta[i], len), | ||
180 | PCI_DMA_BIDIRECTIONAL); | ||
181 | } | ||
182 | |||
159 | /* De-alloc array of command/tx buffers */ | 183 | /* De-alloc array of command/tx buffers */ |
160 | for (i = 0; i <= TFD_CMD_SLOTS; i++) | 184 | for (i = 0; i <= TFD_CMD_SLOTS; i++) |
161 | kfree(txq->cmd[i]); | 185 | kfree(txq->cmd[i]); |
@@ -424,6 +448,14 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
424 | 448 | ||
425 | spin_lock_irqsave(&priv->hcmd_lock, flags); | 449 | spin_lock_irqsave(&priv->hcmd_lock, flags); |
426 | 450 | ||
451 | /* If this is a huge cmd, mark the huge flag also on the meta.flags | ||
452 | * of the _original_ cmd. This is used for DMA mapping clean up. | ||
453 | */ | ||
454 | if (cmd->flags & CMD_SIZE_HUGE) { | ||
455 | idx = get_cmd_index(q, q->write_ptr, 0); | ||
456 | txq->meta[idx].flags = CMD_SIZE_HUGE; | ||
457 | } | ||
458 | |||
427 | idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); | 459 | idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); |
428 | out_cmd = txq->cmd[idx]; | 460 | out_cmd = txq->cmd[idx]; |
429 | out_meta = &txq->meta[idx]; | 461 | out_meta = &txq->meta[idx]; |
@@ -546,6 +578,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
546 | bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); | 578 | bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); |
547 | struct iwl_device_cmd *cmd; | 579 | struct iwl_device_cmd *cmd; |
548 | struct iwl_cmd_meta *meta; | 580 | struct iwl_cmd_meta *meta; |
581 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; | ||
549 | 582 | ||
550 | /* If a Tx command is being handled and it isn't in the actual | 583 | /* If a Tx command is being handled and it isn't in the actual |
551 | * command queue then there a command routing bug has been introduced | 584 | * command queue then there a command routing bug has been introduced |
@@ -559,9 +592,17 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
559 | return; | 592 | return; |
560 | } | 593 | } |
561 | 594 | ||
562 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); | 595 | /* If this is a huge cmd, clear the huge flag on the meta.flags |
563 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; | 596 | * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap |
564 | meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index]; | 597 | * the DMA buffer for the scan (huge) command. |
598 | */ | ||
599 | if (huge) { | ||
600 | cmd_index = get_cmd_index(&txq->q, index, 0); | ||
601 | txq->meta[cmd_index].flags = 0; | ||
602 | } | ||
603 | cmd_index = get_cmd_index(&txq->q, index, huge); | ||
604 | cmd = txq->cmd[cmd_index]; | ||
605 | meta = &txq->meta[cmd_index]; | ||
565 | 606 | ||
566 | pci_unmap_single(priv->pci_dev, | 607 | pci_unmap_single(priv->pci_dev, |
567 | pci_unmap_addr(meta, mapping), | 608 | pci_unmap_addr(meta, mapping), |
@@ -583,6 +624,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
583 | get_cmd_string(cmd->hdr.cmd)); | 624 | get_cmd_string(cmd->hdr.cmd)); |
584 | wake_up_interruptible(&priv->wait_command_queue); | 625 | wake_up_interruptible(&priv->wait_command_queue); |
585 | } | 626 | } |
627 | meta->flags = 0; | ||
586 | } | 628 | } |
587 | EXPORT_SYMBOL(iwl_tx_cmd_complete); | 629 | EXPORT_SYMBOL(iwl_tx_cmd_complete); |
588 | 630 | ||