aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54usb.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/p54usb.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/p54usb.c')
-rw-r--r--drivers/net/wireless/p54/p54usb.c74
1 files changed, 51 insertions, 23 deletions
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 68f1b80f04d9..88fb65046c71 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -135,6 +135,16 @@ static void p54u_rx_cb(struct urb *urb)
135 usb_submit_urb(urb, GFP_ATOMIC); 135 usb_submit_urb(urb, GFP_ATOMIC);
136} 136}
137 137
138static void p54u_tx_reuse_skb_cb(struct urb *urb)
139{
140 struct sk_buff *skb = urb->context;
141 struct p54u_priv *priv = (struct p54u_priv *)((struct ieee80211_hw *)
142 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv;
143
144 skb_pull(skb, priv->common.tx_hdr_len);
145 usb_free_urb(urb);
146}
147
138static void p54u_tx_cb(struct urb *urb) 148static void p54u_tx_cb(struct urb *urb)
139{ 149{
140 usb_free_urb(urb); 150 usb_free_urb(urb);
@@ -146,6 +156,16 @@ static void p54u_tx_free_cb(struct urb *urb)
146 usb_free_urb(urb); 156 usb_free_urb(urb);
147} 157}
148 158
159static void p54u_tx_free_skb_cb(struct urb *urb)
160{
161 struct sk_buff *skb = urb->context;
162 struct ieee80211_hw *dev = (struct ieee80211_hw *)
163 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
164
165 p54_free_skb(dev, skb);
166 usb_free_urb(urb);
167}
168
149static int p54u_init_urbs(struct ieee80211_hw *dev) 169static int p54u_init_urbs(struct ieee80211_hw *dev)
150{ 170{
151 struct p54u_priv *priv = dev->priv; 171 struct p54u_priv *priv = dev->priv;
@@ -192,8 +212,8 @@ static void p54u_free_urbs(struct ieee80211_hw *dev)
192 } 212 }
193} 213}
194 214
195static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data, 215static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
196 size_t len, int free_on_tx) 216 int free_on_tx)
197{ 217{
198 struct p54u_priv *priv = dev->priv; 218 struct p54u_priv *priv = dev->priv;
199 struct urb *addr_urb, *data_urb; 219 struct urb *addr_urb, *data_urb;
@@ -209,11 +229,14 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
209 } 229 }
210 230
211 usb_fill_bulk_urb(addr_urb, priv->udev, 231 usb_fill_bulk_urb(addr_urb, priv->udev,
212 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id, 232 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
213 sizeof(data->req_id), p54u_tx_cb, dev); 233 &((struct p54_control_hdr *)skb->data)->req_id, 4,
234 p54u_tx_cb, dev);
214 usb_fill_bulk_urb(data_urb, priv->udev, 235 usb_fill_bulk_urb(data_urb, priv->udev,
215 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len, 236 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
216 free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev); 237 skb->data, skb->len,
238 free_on_tx ? p54u_tx_free_skb_cb :
239 p54u_tx_reuse_skb_cb, skb);
217 240
218 usb_submit_urb(addr_urb, GFP_ATOMIC); 241 usb_submit_urb(addr_urb, GFP_ATOMIC);
219 usb_submit_urb(data_urb, GFP_ATOMIC); 242 usb_submit_urb(data_urb, GFP_ATOMIC);
@@ -232,31 +255,35 @@ static __le32 p54u_lm87_chksum(const u32 *data, size_t length)
232 return cpu_to_le32(chk); 255 return cpu_to_le32(chk);
233} 256}
234 257
235static void p54u_tx_lm87(struct ieee80211_hw *dev, 258static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb,
236 struct p54_control_hdr *data, 259 int free_on_tx)
237 size_t len, int free_on_tx)
238{ 260{
239 struct p54u_priv *priv = dev->priv; 261 struct p54u_priv *priv = dev->priv;
240 struct urb *data_urb; 262 struct urb *data_urb;
241 struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr); 263 struct lm87_tx_hdr *hdr;
264 __le32 checksum;
265 __le32 addr = ((struct p54_control_hdr *)skb->data)->req_id;
242 266
243 data_urb = usb_alloc_urb(0, GFP_ATOMIC); 267 data_urb = usb_alloc_urb(0, GFP_ATOMIC);
244 if (!data_urb) 268 if (!data_urb)
245 return; 269 return;
246 270
247 hdr->chksum = p54u_lm87_chksum((u32 *)data, len); 271 checksum = p54u_lm87_chksum((u32 *)skb->data, skb->len);
248 hdr->device_addr = data->req_id; 272 hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr));
273 hdr->chksum = checksum;
274 hdr->device_addr = addr;
249 275
250 usb_fill_bulk_urb(data_urb, priv->udev, 276 usb_fill_bulk_urb(data_urb, priv->udev,
251 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, 277 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
252 len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, 278 skb->data, skb->len,
253 dev); 279 free_on_tx ? p54u_tx_free_skb_cb :
280 p54u_tx_reuse_skb_cb, skb);
254 281
255 usb_submit_urb(data_urb, GFP_ATOMIC); 282 usb_submit_urb(data_urb, GFP_ATOMIC);
256} 283}
257 284
258static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data, 285static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
259 size_t len, int free_on_tx) 286 int free_on_tx)
260{ 287{
261 struct p54u_priv *priv = dev->priv; 288 struct p54u_priv *priv = dev->priv;
262 struct urb *int_urb, *data_urb; 289 struct urb *int_urb, *data_urb;
@@ -284,11 +311,10 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *da
284 reg->addr = cpu_to_le32(P54U_DEV_BASE); 311 reg->addr = cpu_to_le32(P54U_DEV_BASE);
285 reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA); 312 reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
286 313
287 len += sizeof(*data); 314 hdr = (void *)skb_push(skb, sizeof(*hdr));
288 hdr = (void *)data - sizeof(*hdr);
289 memset(hdr, 0, sizeof(*hdr)); 315 memset(hdr, 0, sizeof(*hdr));
290 hdr->device_addr = data->req_id; 316 hdr->device_addr = ((struct p54_control_hdr *)skb->data)->req_id;
291 hdr->len = cpu_to_le16(len); 317 hdr->len = cpu_to_le16(skb->len + sizeof(struct p54_control_hdr));
292 318
293 usb_fill_bulk_urb(int_urb, priv->udev, 319 usb_fill_bulk_urb(int_urb, priv->udev,
294 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), 320 usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
@@ -296,8 +322,10 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *da
296 usb_submit_urb(int_urb, GFP_ATOMIC); 322 usb_submit_urb(int_urb, GFP_ATOMIC);
297 323
298 usb_fill_bulk_urb(data_urb, priv->udev, 324 usb_fill_bulk_urb(data_urb, priv->udev,
299 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr), 325 usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
300 free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev); 326 skb->data, skb->len,
327 free_on_tx ? p54u_tx_free_skb_cb :
328 p54u_tx_reuse_skb_cb, skb);
301 usb_submit_urb(data_urb, GFP_ATOMIC); 329 usb_submit_urb(data_urb, GFP_ATOMIC);
302} 330}
303 331