summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54pci.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2008-10-15 04:07:16 +0200
committerJohn W. Linville <linville@tuxdriver.com>2008-11-01 00:00:33 +0100
commitb92f30d65aeb0502e2ed8beb80c8465578b40002 (patch)
tree7d2669d864df5368377dcad11c1bbf4be266eff5 /drivers/net/wireless/p54/p54pci.c
parentp54: p54: refactor p54_rx_frame_sent (diff)
downloadlinux-b92f30d65aeb0502e2ed8beb80c8465578b40002.tar.xz
linux-b92f30d65aeb0502e2ed8beb80c8465578b40002.zip
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,
while (i != idx) {
desc = &ring[i];
- kfree(tx_buf[i]);
+ p54_free_skb(dev, tx_buf[i]);
tx_buf[i] = NULL;
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)
return reg ? IRQ_HANDLED : IRQ_NONE;
}
-static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
- size_t len, int free_on_tx)
+static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ int free_on_tx)
{
struct p54p_priv *priv = dev->priv;
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,
idx = le32_to_cpu(ring_control->host_idx[1]);
i = idx % ARRAY_SIZE(ring_control->tx_data);
- mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
+ mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
desc = &ring_control->tx_data[i];
desc->host_addr = cpu_to_le32(mapping);
- desc->device_addr = data->req_id;
- desc->len = cpu_to_le16(len);
+ desc->device_addr = ((struct p54_control_hdr *)skb->data)->req_id;
+ desc->len = cpu_to_le16(skb->len);
desc->flags = 0;
wmb();
ring_control->host_idx[1] = cpu_to_le32(idx + 1);
if (free_on_tx)
- priv->tx_buf_data[i] = data;
+ priv->tx_buf_data[i] = skb;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -342,8 +343,10 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
/* FIXME: unlikely to happen because the device usually runs out of
memory before we fill the ring up, but we can make it impossible */
- if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
+ if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2) {
+ p54_free_skb(dev, skb);
printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
+ }
}
static void p54p_stop(struct ieee80211_hw *dev)
@@ -393,7 +396,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
le16_to_cpu(desc->len),
PCI_DMA_TODEVICE);
- kfree(priv->tx_buf_data[i]);
+ p54_free_skb(dev, priv->tx_buf_data[i]);
priv->tx_buf_data[i] = NULL;
}
@@ -405,7 +408,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
le16_to_cpu(desc->len),
PCI_DMA_TODEVICE);
- kfree(priv->tx_buf_mgmt[i]);
+ p54_free_skb(dev, priv->tx_buf_mgmt[i]);
priv->tx_buf_mgmt[i] = NULL;
}