aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54pci.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2008-10-14 22:07:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:00:33 -0400
commitb92f30d65aeb0502e2ed8beb80c8465578b40002 (patch)
tree7d2669d864df5368377dcad11c1bbf4be266eff5 /drivers/net/wireless/p54/p54pci.c
parent9de5776ff33a006b864341a6ec8d31f1a3c628cf (diff)
p54: fix memory management
We have to be careful if multiple "control frames" are passed in a very short intervals to the device's firmware. As p54_assign_address always put them into same memory location. To guarantee that this won't happen anymore, we have to treat control frames like normal data frames in the devices own memory management. Signed-off-by: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54/p54pci.c')
-rw-r--r--drivers/net/wireless/p54/p54pci.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index bba2c90e533f..1bb9584f0355 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -235,7 +235,7 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
235 235
236 while (i != idx) { 236 while (i != idx) {
237 desc = &ring[i]; 237 desc = &ring[i];
238 kfree(tx_buf[i]); 238 p54_free_skb(dev, tx_buf[i]);
239 tx_buf[i] = NULL; 239 tx_buf[i] = NULL;
240 240
241 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), 241 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
@@ -306,8 +306,8 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
306 return reg ? IRQ_HANDLED : IRQ_NONE; 306 return reg ? IRQ_HANDLED : IRQ_NONE;
307} 307}
308 308
309static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data, 309static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
310 size_t len, int free_on_tx) 310 int free_on_tx)
311{ 311{
312 struct p54p_priv *priv = dev->priv; 312 struct p54p_priv *priv = dev->priv;
313 struct p54p_ring_control *ring_control = priv->ring_control; 313 struct p54p_ring_control *ring_control = priv->ring_control;
@@ -322,18 +322,19 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
322 idx = le32_to_cpu(ring_control->host_idx[1]); 322 idx = le32_to_cpu(ring_control->host_idx[1]);
323 i = idx % ARRAY_SIZE(ring_control->tx_data); 323 i = idx % ARRAY_SIZE(ring_control->tx_data);
324 324
325 mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE); 325 mapping = pci_map_single(priv->pdev, skb->data, skb->len,
326 PCI_DMA_TODEVICE);
326 desc = &ring_control->tx_data[i]; 327 desc = &ring_control->tx_data[i];
327 desc->host_addr = cpu_to_le32(mapping); 328 desc->host_addr = cpu_to_le32(mapping);
328 desc->device_addr = data->req_id; 329 desc->device_addr = ((struct p54_control_hdr *)skb->data)->req_id;
329 desc->len = cpu_to_le16(len); 330 desc->len = cpu_to_le16(skb->len);
330 desc->flags = 0; 331 desc->flags = 0;
331 332
332 wmb(); 333 wmb();
333 ring_control->host_idx[1] = cpu_to_le32(idx + 1); 334 ring_control->host_idx[1] = cpu_to_le32(idx + 1);
334 335
335 if (free_on_tx) 336 if (free_on_tx)
336 priv->tx_buf_data[i] = data; 337 priv->tx_buf_data[i] = skb;
337 338
338 spin_unlock_irqrestore(&priv->lock, flags); 339 spin_unlock_irqrestore(&priv->lock, flags);
339 340
@@ -342,8 +343,10 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
342 343
343 /* FIXME: unlikely to happen because the device usually runs out of 344 /* FIXME: unlikely to happen because the device usually runs out of
344 memory before we fill the ring up, but we can make it impossible */ 345 memory before we fill the ring up, but we can make it impossible */
345 if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2) 346 if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2) {
347 p54_free_skb(dev, skb);
346 printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy)); 348 printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
349 }
347} 350}
348 351
349static void p54p_stop(struct ieee80211_hw *dev) 352static void p54p_stop(struct ieee80211_hw *dev)
@@ -393,7 +396,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
393 le16_to_cpu(desc->len), 396 le16_to_cpu(desc->len),
394 PCI_DMA_TODEVICE); 397 PCI_DMA_TODEVICE);
395 398
396 kfree(priv->tx_buf_data[i]); 399 p54_free_skb(dev, priv->tx_buf_data[i]);
397 priv->tx_buf_data[i] = NULL; 400 priv->tx_buf_data[i] = NULL;
398 } 401 }
399 402
@@ -405,7 +408,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
405 le16_to_cpu(desc->len), 408 le16_to_cpu(desc->len),
406 PCI_DMA_TODEVICE); 409 PCI_DMA_TODEVICE);
407 410
408 kfree(priv->tx_buf_mgmt[i]); 411 p54_free_skb(dev, priv->tx_buf_mgmt[i]);
409 priv->tx_buf_mgmt[i] = NULL; 412 priv->tx_buf_mgmt[i] = NULL;
410 } 413 }
411 414