aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2010-03-22 05:28:41 -0400
committerReinette Chatre <reinette.chatre@intel.com>2010-04-02 14:12:20 -0400
commitdd48744964296b5713032ea1d66eb9e3d990e287 (patch)
tree6ddda6cee4b7ba9848b568456083993f42b25c21 /drivers/net
parent7371400431389e1df6a2a05ab9882055b8a6ff2c (diff)
iwlwifi: fix DMA allocation warnings
Below warning is triggered sometimes at module removal time when CONFIG_DMA_API_DEBUG is enabled. This should be caused by we didn't unmap pending commands (enqueued, but no complete notification received) for the Tx command queue. [ 1583.107469] ------------[ cut here ]------------ [ 1583.107539] WARNING: at lib/dma-debug.c:688 dma_debug_device_change+0x13c/0x180() [ 1583.107617] Hardware name: ... [ 1583.107664] pci 0000:04:00.0: DMA-API: device driver has pending DMA allocations while released from device [count=1] [ 1583.107713] Modules linked in: ... [ 1583.111661] Pid: 16970, comm: modprobe Tainted: G W 2.6.34-rc1-wl #33 [ 1583.111727] Call Trace: [ 1583.111779] [<c02a281c>] ? dma_debug_device_change+0x13c/0x180 [ 1583.111833] [<c02a281c>] ? dma_debug_device_change+0x13c/0x180 [ 1583.111908] [<c0138e11>] warn_slowpath_common+0x71/0xd0 [ 1583.111963] [<c02a281c>] ? dma_debug_device_change+0x13c/0x180 [ 1583.112016] [<c0138ebb>] warn_slowpath_fmt+0x2b/0x30 [ 1583.112086] [<c02a281c>] dma_debug_device_change+0x13c/0x180 [ 1583.112142] [<c03e6c33>] notifier_call_chain+0x53/0x90 [ 1583.112198] [<c03e1ebe>] ? down_read+0x6e/0x90 [ 1583.112271] [<c015b229>] __blocking_notifier_call_chain+0x49/0x70 [ 1583.112326] [<c015b26f>] blocking_notifier_call_chain+0x1f/0x30 [ 1583.112380] [<c031931c>] __device_release_driver+0x8c/0xa0 [ 1583.112451] [<c03193bf>] driver_detach+0x8f/0xa0 [ 1583.112538] [<c0318382>] bus_remove_driver+0x82/0x100 [ 1583.112595] [<c0319ad9>] driver_unregister+0x49/0x80 [ 1583.112671] [<c024feb2>] ? sysfs_remove_file+0x12/0x20 [ 1583.112727] [<c02aa292>] pci_unregister_driver+0x32/0x80 [ 1583.112791] [<fc13a3c1>] iwl_exit+0x12/0x19 [iwlagn] [ 1583.112848] [<c017940a>] sys_delete_module+0x15a/0x210 [ 1583.112870] [<c015a5db>] ? up_read+0x1b/0x30 [ 1583.112893] [<c029600c>] ? trace_hardirqs_off_thunk+0xc/0x10 [ 1583.112924] [<c0295ffc>] ? trace_hardirqs_on_thunk+0xc/0x10 [ 1583.112947] [<c03e6a1f>] ? do_page_fault+0x1ff/0x3c0 [ 1583.112978] [<c03e36f6>] ? restore_all_notrace+0x0/0x18 [ 1583.113002] [<c016aa70>] ? trace_hardirqs_on_caller+0x20/0x190 [ 1583.113025] [<c0102d58>] sysenter_do_call+0x12/0x38 [ 1583.113054] ---[ end trace fc23e059cc4c2ced ]--- Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers/net')
-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